神刀安全网

iOS: View Controller Data Injection with Storyboards and Segues in Swift

Since I openly declared my love for Storyboards & Nibs earlier this week, I’ve gotten a lot of questions on how I deal with injecting dependencies between View Controllers without using a custom initializer. So I’ll share that now.

But first, I’d like to say that my solution is not perfect, and it’s a workaround around how UIViewController works. Hopefully Apple will provide a more flexible and Swifty UIKit API (with protocols instead of subclassing!) down the line that will allow the very common case of dependency injection!

Second, the reason I’m a against messing with the initializers is because we have to subclass our UIViewControllers from UIKit. There are already several initializers there and we have to call super on them because UIKit is doing work behind the scenes (which we cannot see the source code of):

// comments from Apple's UIViewController code /*       The designated initializer. If you subclass UIViewController, you must call the super implementation of this       method, even if you aren't using a NIB.  (As a convenience, the default init method will do this for you,       and specify nil for both of this methods arguments.) In the specified NIB, the File's Owner proxy should       have its class set to your view controller subclass, with the view outlet connected to the main view. If you       invoke this method with a nil nib name, then this class' -loadView method will attempt to load a NIB whose       name is the same as your view controller's class. If no such NIB in fact exists then you must either call       -setView: before -view is invoked, or override the -loadView method to set up your views programatically.     */     publicinit(nibNamenibNameOrNil: String?, bundlenibBundleOrNil: NSBundle?)     publicinit?(coderaDecoder: NSCoder) 

Sure, it’s been the same for while and will likely not change, but since I don’t have control or visibility into UIKit, I prefer to work with how it’s meant to be used rather than against it by creating my own clever initializers!

So the way I prefer to handle this issue is by using Implicitly Unwrapped Optionals :scream::scream::scream:

I’ll use this project as an example . The detail view controller – the one that depends on a value from the previous view controller, has an implicitly unwrapped optional variable for the value that it absolutely needs at the time that it’s initialized or loaded:

// Detail View Controller import UIKit   class RedPillViewController:UIViewController {       @IBOutletweak privatevar mainLabel: UILabel!          // The Implicitly unwrapped optional!     var mainText: String!          override func viewDidLoad() {         super.viewDidLoad()           // it's used here!         mainLabel.text = mainText     }   } 

In this case, if mainText is NOT assigned in prepareForSegue , this view controller will immediately crash :boom: This will make it super easy for the developer writing this code to immediately address the problem and assign the dependency:

// In the Parent / More General View Controller     override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {                  switch segueIdentifierForSegue(segue) {                      case .TheRedPillExperience:             let redPillVC = segue.destinationViewController as! RedPillViewController             // assigning the implicitly unwrapped optional here!             redPillVC.mainText = ":smiling_imp:"         case .TheBluePillExperience:             let bluePillVC = segue.destinationViewController as! BluePillViewController             // assigning the implicitly unwrapped optional here!             bluePillVC.mainText = ":angel:"         }     } 

The key is to make sure that the implicitly unused optional is assigned or used during the detail view controller’s initialization / view loading cycle ! If it’s used later on, the view controller will not crash when the implicitly unwrapped optional is passed in as @justMaku points out:

@NatashaTheRobot I’m talking about situation like this, this will work as long we don’t call doFeatureX. pic.twitter.com/RyjsU4quWf

— Michał Kałużny (@justMaku) March 27, 2016

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » iOS: View Controller Data Injection with Storyboards and Segues in Swift

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮