Declare array as property of class and use it in Swift












1














I have a cooking app, where I have meal with name, and cooking steps, which are presented as an array of strings:



class Meal {    
var name: String
var steps: Array<String>?
}


And then I try to pass the data to view:



override func viewDidLoad() { 
super.viewDidLoad()

// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self

// Set up views if editing an existing Meal.
if let meal = meal {
nameTextField.text = meal.name
}
createLabelAndText()
}


The createLabelAndText method should create for each element of an array label - something like Step 1, Step 2 and textView



  func createLabel() {

for (index, element) in (meal?.steps){
let myLabel = UILabel()

//Assigning value or text to label
myLabel.text = "Step (index)"

//Assigning frame to the label
myLabel.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
self.view.addSubview(myLabel)
self.view.addSubview(textView)
}
}


And what I want to get is something like this:
[http://a1.mzstatic.com/us/r30/Purple30/v4/24/3e/64/243e64b5-79cf-9a35-5386-d81ed250b926/screen696x696.jpeg][1]



Right now I have a problem - I can't loop trough meal?.steps and get the error Type '[Any]?' does not conform to protocol 'Sequence'



Also I try to configure a view controller before it's presented. But it doesn't allow me to access and assign steps from class meal.



override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
let name = nameTextField.text ?? ""
let steps = meal?.steps
// Set the meal to be passed to MealTableViewController after the unwind segue.
meal = Meal(name: name, steps: steps )

}


How could I solve this problems or maybe there are some better approaches?










share|improve this question


















  • 1




    step is an optional, too, so you have to unwrap it before using it.
    – Rob
    Nov 19 '18 at 19:56








  • 1




    Also, why not use a table view?
    – Paulw11
    Nov 19 '18 at 20:16
















1














I have a cooking app, where I have meal with name, and cooking steps, which are presented as an array of strings:



class Meal {    
var name: String
var steps: Array<String>?
}


And then I try to pass the data to view:



override func viewDidLoad() { 
super.viewDidLoad()

// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self

// Set up views if editing an existing Meal.
if let meal = meal {
nameTextField.text = meal.name
}
createLabelAndText()
}


The createLabelAndText method should create for each element of an array label - something like Step 1, Step 2 and textView



  func createLabel() {

for (index, element) in (meal?.steps){
let myLabel = UILabel()

//Assigning value or text to label
myLabel.text = "Step (index)"

//Assigning frame to the label
myLabel.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
self.view.addSubview(myLabel)
self.view.addSubview(textView)
}
}


And what I want to get is something like this:
[http://a1.mzstatic.com/us/r30/Purple30/v4/24/3e/64/243e64b5-79cf-9a35-5386-d81ed250b926/screen696x696.jpeg][1]



Right now I have a problem - I can't loop trough meal?.steps and get the error Type '[Any]?' does not conform to protocol 'Sequence'



Also I try to configure a view controller before it's presented. But it doesn't allow me to access and assign steps from class meal.



override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
let name = nameTextField.text ?? ""
let steps = meal?.steps
// Set the meal to be passed to MealTableViewController after the unwind segue.
meal = Meal(name: name, steps: steps )

}


How could I solve this problems or maybe there are some better approaches?










share|improve this question


















  • 1




    step is an optional, too, so you have to unwrap it before using it.
    – Rob
    Nov 19 '18 at 19:56








  • 1




    Also, why not use a table view?
    – Paulw11
    Nov 19 '18 at 20:16














1












1








1







I have a cooking app, where I have meal with name, and cooking steps, which are presented as an array of strings:



class Meal {    
var name: String
var steps: Array<String>?
}


And then I try to pass the data to view:



override func viewDidLoad() { 
super.viewDidLoad()

// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self

// Set up views if editing an existing Meal.
if let meal = meal {
nameTextField.text = meal.name
}
createLabelAndText()
}


The createLabelAndText method should create for each element of an array label - something like Step 1, Step 2 and textView



  func createLabel() {

for (index, element) in (meal?.steps){
let myLabel = UILabel()

//Assigning value or text to label
myLabel.text = "Step (index)"

//Assigning frame to the label
myLabel.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
self.view.addSubview(myLabel)
self.view.addSubview(textView)
}
}


And what I want to get is something like this:
[http://a1.mzstatic.com/us/r30/Purple30/v4/24/3e/64/243e64b5-79cf-9a35-5386-d81ed250b926/screen696x696.jpeg][1]



Right now I have a problem - I can't loop trough meal?.steps and get the error Type '[Any]?' does not conform to protocol 'Sequence'



Also I try to configure a view controller before it's presented. But it doesn't allow me to access and assign steps from class meal.



override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
let name = nameTextField.text ?? ""
let steps = meal?.steps
// Set the meal to be passed to MealTableViewController after the unwind segue.
meal = Meal(name: name, steps: steps )

}


How could I solve this problems or maybe there are some better approaches?










share|improve this question













I have a cooking app, where I have meal with name, and cooking steps, which are presented as an array of strings:



class Meal {    
var name: String
var steps: Array<String>?
}


And then I try to pass the data to view:



override func viewDidLoad() { 
super.viewDidLoad()

// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self

// Set up views if editing an existing Meal.
if let meal = meal {
nameTextField.text = meal.name
}
createLabelAndText()
}


The createLabelAndText method should create for each element of an array label - something like Step 1, Step 2 and textView



  func createLabel() {

for (index, element) in (meal?.steps){
let myLabel = UILabel()

//Assigning value or text to label
myLabel.text = "Step (index)"

//Assigning frame to the label
myLabel.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
self.view.addSubview(myLabel)
self.view.addSubview(textView)
}
}


And what I want to get is something like this:
[http://a1.mzstatic.com/us/r30/Purple30/v4/24/3e/64/243e64b5-79cf-9a35-5386-d81ed250b926/screen696x696.jpeg][1]



Right now I have a problem - I can't loop trough meal?.steps and get the error Type '[Any]?' does not conform to protocol 'Sequence'



Also I try to configure a view controller before it's presented. But it doesn't allow me to access and assign steps from class meal.



override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
let name = nameTextField.text ?? ""
let steps = meal?.steps
// Set the meal to be passed to MealTableViewController after the unwind segue.
meal = Meal(name: name, steps: steps )

}


How could I solve this problems or maybe there are some better approaches?







ios swift xcode






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 19 '18 at 19:52









Anna FAnna F

4921415




4921415








  • 1




    step is an optional, too, so you have to unwrap it before using it.
    – Rob
    Nov 19 '18 at 19:56








  • 1




    Also, why not use a table view?
    – Paulw11
    Nov 19 '18 at 20:16














  • 1




    step is an optional, too, so you have to unwrap it before using it.
    – Rob
    Nov 19 '18 at 19:56








  • 1




    Also, why not use a table view?
    – Paulw11
    Nov 19 '18 at 20:16








1




1




step is an optional, too, so you have to unwrap it before using it.
– Rob
Nov 19 '18 at 19:56






step is an optional, too, so you have to unwrap it before using it.
– Rob
Nov 19 '18 at 19:56






1




1




Also, why not use a table view?
– Paulw11
Nov 19 '18 at 20:16




Also, why not use a table view?
– Paulw11
Nov 19 '18 at 20:16












1 Answer
1






active

oldest

votes


















2














You need to unwrap steps, because not only is meal an optional, but so is steps. E.g.



func createLabel() {
guard let steps = meal?.steps else { return }

for (index, element) in steps.enumerated() {
let label = UILabel()

//Assigning value or text to label
label.text = "Step (index)"

//Assigning frame to the label
label.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
view.addSubview(label)
view.addSubview(textView)
}
}


Obviously, if you want the index as you enumerate through steps, you need to use enumerated(), too.



As an aside, I'm not sure why you're setting your text view to have the same frame as the label, effectively putting it on top of the label, but that's beyond the scope of this question. The main issue here is just to make sure you unwrap your steps optional before trying to use it.






share|improve this answer





















  • thanks a lot! it helped! One more question - how would you advice to go with label + text? Are there some good practices?
    – Anna F
    Nov 19 '18 at 20:23






  • 2




    When adding a series of subviews, a table view or collection view is great when it's an arbitrarily long list. If you know it won't exceed a certain number that can be shown at a given time, a stack view is good. Regarding the text view and label combination, the question is what is the purpose of the label. If it's to show some text until the user enters something, then use placeholder text in the text field and eliminate the label entirely. If you want to see the label and the text field at the same time, you probably just don't put them on top of each other, i.e. adjust their frames.
    – Rob
    Nov 19 '18 at 20:31











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381708%2fdeclare-array-as-property-of-class-and-use-it-in-swift%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














You need to unwrap steps, because not only is meal an optional, but so is steps. E.g.



func createLabel() {
guard let steps = meal?.steps else { return }

for (index, element) in steps.enumerated() {
let label = UILabel()

//Assigning value or text to label
label.text = "Step (index)"

//Assigning frame to the label
label.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
view.addSubview(label)
view.addSubview(textView)
}
}


Obviously, if you want the index as you enumerate through steps, you need to use enumerated(), too.



As an aside, I'm not sure why you're setting your text view to have the same frame as the label, effectively putting it on top of the label, but that's beyond the scope of this question. The main issue here is just to make sure you unwrap your steps optional before trying to use it.






share|improve this answer





















  • thanks a lot! it helped! One more question - how would you advice to go with label + text? Are there some good practices?
    – Anna F
    Nov 19 '18 at 20:23






  • 2




    When adding a series of subviews, a table view or collection view is great when it's an arbitrarily long list. If you know it won't exceed a certain number that can be shown at a given time, a stack view is good. Regarding the text view and label combination, the question is what is the purpose of the label. If it's to show some text until the user enters something, then use placeholder text in the text field and eliminate the label entirely. If you want to see the label and the text field at the same time, you probably just don't put them on top of each other, i.e. adjust their frames.
    – Rob
    Nov 19 '18 at 20:31
















2














You need to unwrap steps, because not only is meal an optional, but so is steps. E.g.



func createLabel() {
guard let steps = meal?.steps else { return }

for (index, element) in steps.enumerated() {
let label = UILabel()

//Assigning value or text to label
label.text = "Step (index)"

//Assigning frame to the label
label.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
view.addSubview(label)
view.addSubview(textView)
}
}


Obviously, if you want the index as you enumerate through steps, you need to use enumerated(), too.



As an aside, I'm not sure why you're setting your text view to have the same frame as the label, effectively putting it on top of the label, but that's beyond the scope of this question. The main issue here is just to make sure you unwrap your steps optional before trying to use it.






share|improve this answer





















  • thanks a lot! it helped! One more question - how would you advice to go with label + text? Are there some good practices?
    – Anna F
    Nov 19 '18 at 20:23






  • 2




    When adding a series of subviews, a table view or collection view is great when it's an arbitrarily long list. If you know it won't exceed a certain number that can be shown at a given time, a stack view is good. Regarding the text view and label combination, the question is what is the purpose of the label. If it's to show some text until the user enters something, then use placeholder text in the text field and eliminate the label entirely. If you want to see the label and the text field at the same time, you probably just don't put them on top of each other, i.e. adjust their frames.
    – Rob
    Nov 19 '18 at 20:31














2












2








2






You need to unwrap steps, because not only is meal an optional, but so is steps. E.g.



func createLabel() {
guard let steps = meal?.steps else { return }

for (index, element) in steps.enumerated() {
let label = UILabel()

//Assigning value or text to label
label.text = "Step (index)"

//Assigning frame to the label
label.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
view.addSubview(label)
view.addSubview(textView)
}
}


Obviously, if you want the index as you enumerate through steps, you need to use enumerated(), too.



As an aside, I'm not sure why you're setting your text view to have the same frame as the label, effectively putting it on top of the label, but that's beyond the scope of this question. The main issue here is just to make sure you unwrap your steps optional before trying to use it.






share|improve this answer












You need to unwrap steps, because not only is meal an optional, but so is steps. E.g.



func createLabel() {
guard let steps = meal?.steps else { return }

for (index, element) in steps.enumerated() {
let label = UILabel()

//Assigning value or text to label
label.text = "Step (index)"

//Assigning frame to the label
label.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

let textView = UITextView()
textView.text = element
textView.frame = CGRect(x: 10, y: index*100, width: 200, height: 30)

//Finally we need to add label to view to display it on screen.
view.addSubview(label)
view.addSubview(textView)
}
}


Obviously, if you want the index as you enumerate through steps, you need to use enumerated(), too.



As an aside, I'm not sure why you're setting your text view to have the same frame as the label, effectively putting it on top of the label, but that's beyond the scope of this question. The main issue here is just to make sure you unwrap your steps optional before trying to use it.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 19 '18 at 20:07









RobRob

296k47550719




296k47550719












  • thanks a lot! it helped! One more question - how would you advice to go with label + text? Are there some good practices?
    – Anna F
    Nov 19 '18 at 20:23






  • 2




    When adding a series of subviews, a table view or collection view is great when it's an arbitrarily long list. If you know it won't exceed a certain number that can be shown at a given time, a stack view is good. Regarding the text view and label combination, the question is what is the purpose of the label. If it's to show some text until the user enters something, then use placeholder text in the text field and eliminate the label entirely. If you want to see the label and the text field at the same time, you probably just don't put them on top of each other, i.e. adjust their frames.
    – Rob
    Nov 19 '18 at 20:31


















  • thanks a lot! it helped! One more question - how would you advice to go with label + text? Are there some good practices?
    – Anna F
    Nov 19 '18 at 20:23






  • 2




    When adding a series of subviews, a table view or collection view is great when it's an arbitrarily long list. If you know it won't exceed a certain number that can be shown at a given time, a stack view is good. Regarding the text view and label combination, the question is what is the purpose of the label. If it's to show some text until the user enters something, then use placeholder text in the text field and eliminate the label entirely. If you want to see the label and the text field at the same time, you probably just don't put them on top of each other, i.e. adjust their frames.
    – Rob
    Nov 19 '18 at 20:31
















thanks a lot! it helped! One more question - how would you advice to go with label + text? Are there some good practices?
– Anna F
Nov 19 '18 at 20:23




thanks a lot! it helped! One more question - how would you advice to go with label + text? Are there some good practices?
– Anna F
Nov 19 '18 at 20:23




2




2




When adding a series of subviews, a table view or collection view is great when it's an arbitrarily long list. If you know it won't exceed a certain number that can be shown at a given time, a stack view is good. Regarding the text view and label combination, the question is what is the purpose of the label. If it's to show some text until the user enters something, then use placeholder text in the text field and eliminate the label entirely. If you want to see the label and the text field at the same time, you probably just don't put them on top of each other, i.e. adjust their frames.
– Rob
Nov 19 '18 at 20:31




When adding a series of subviews, a table view or collection view is great when it's an arbitrarily long list. If you know it won't exceed a certain number that can be shown at a given time, a stack view is good. Regarding the text view and label combination, the question is what is the purpose of the label. If it's to show some text until the user enters something, then use placeholder text in the text field and eliminate the label entirely. If you want to see the label and the text field at the same time, you probably just don't put them on top of each other, i.e. adjust their frames.
– Rob
Nov 19 '18 at 20:31


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381708%2fdeclare-array-as-property-of-class-and-use-it-in-swift%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith