简体   繁体   中英

SWIFT - Property not seen outside viewdidload

I try to pass a string from a VC1 to VC2, but the value of tex passed into property detailItem as loaded only into viewdidload, and not in the function

viewcontroller 1:

@IBOutlet var tex: UITextField!
// Prepare fore segue pass the value of txt

 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  if segue.identifier? == "Todo" {
    let navVC = segue.destinationViewController as UINavigationController
    let itemVC: ChecklistViewController = navVC.topViewController as ChecklistViewController
    itemVC.detailItem! = tex.text
  }
 }

viewcontroller 2:

var detailItem : String!

// I can see the value of tex only in the ViewDidLoad

override func viewDidLoad() {
  super.viewDidLoad()

  println("viewDidLoad \(detailItem)")
  tableView.rowHeight = 44
}

// Here and in  the function below result nil.
required init(coder aDecoder: NSCoder) {
  println("print init \(detailItem)")
  items = [ChecklistItem]()
  super.init(coder: aDecoder)
  loadChecklistItems()
}

func documentsDirectory() -> String {
  let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as [String]
  return paths[0]
}

func dataFilePath() -> String {
  println("print path\(detailItem)")
  return documentsDirectory().stringByAppendingPathComponent("Checklists.plist")
}

func saveChecklistItems() {
  let data = NSMutableData()
  let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
  archiver.encodeObject(items, forKey: "ChecklistItems")
  archiver.finishEncoding()
  data.writeToFile(dataFilePath(), atomically: true)
  println("print save\(detailItem)")
}

func loadChecklistItems() {
  let path = dataFilePath()
  if NSFileManager.defaultManager().fileExistsAtPath(path) {
    if let data = NSData(contentsOfFile: path) {
      println("print load\(detailItem)")
      let unarchiver = NSKeyedUnarchiver(forReadingWithData: data)
      items = unarchiver.decodeObjectForKey("ChecklistItems") as [ChecklistItem]
      unarchiver.finishDecoding()
    }
  }
}

Console Output:

print init 
print path
print load
viewDidLoad Antwerp

Thanks Alberto

The reason is because when prepareForSegue is called your viewcontroller 2 has already been created and viewDidLoad has been called.

Check out This Link as it has a nice writeup of the view lifecycle

You will be able to see the property in all other functions that are called after viewDidLoad. Because you are setting the property after you are creating the view, so those functions are called first, when the property hasn't been set by you.

Try calling your functions in viewDidLoad.

You can't see this property in the initializer because that code is called before itemVC.detailItem! = tex.text itemVC.detailItem! = tex.text .

You could move your call to loadChecklistItems() into viewDidLoad() . You could also load the items as soon as the detail item is set:

var detailItem : String! {
    didSet {
        loadChecklistItems()
    }
}

According to the lifecycle of UIViewController, the viewDidLoad method is called exactly to let you know that the controller's view and, what's interesting for us in this case, all IBOutlets. This means that you're allowed to rely on your outlets' state only since viewDidLoad is called. For more information please refer to "UIViewController Class Reference" at https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/ .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM