This is probably the best pattern to deal with this, since there are a number 
of ugly problems to deal with if passing an incomplete object around. 
initializers exist with a lot of special case rules around self because they 
are reusing the term for something that is actually not yet self, but an 
incubating object.

There are challenges just in passing this incubating self into another function 
or static method, or (even worse) calling a method on that incomplete object 
which might be dynamically dispatched. For example, you may require 
synthesizing something self-like to pass around instead, and have to create new 
versions of the functions that can operate with the structure and honor rules 
about the behavior if say a read against an uninitialized videoPlayerLayer 
happens. Even solving the problems of making this work, you would need to 
deterministically know the values were set (including in the case where the 
method you called was actually redefined by a subclass in another module), and 
apply them back into the incubating self object.

tl;dr initializers are complex and the language has restrictions and 
requirements around initializers to hide complexity and enforce safety.

-DW


> On Apr 30, 2016, at 12:18 PM, Hooman Mehr via swift-evolution 
> <[email protected]> wrote:
> 
> Besides the ages old designated initializer pattern that is already suggested 
> (having a few designated initializers and a bunch of convenience 
> initializers), this is how I have been dealing with this since Swift 1.0:
> 
> import UIKit
> import AVFoundation
> 
> class SomeViewController: UIViewController {
>     
>     private typealias My = SomeViewController
>     
>     // MARK: Properties
>     
>     private var videoPlayer: AVPlayer
>     private var videoPlayerLayer: AVPlayerLayer
>     
>     // MARK: - Object Lifecycle
>     
>     override init(nibName: String?, bundle nibBundle: NSBundle?) {
> 
>         
>         (videoPlayer, videoPlayerLayer) = My.commonInitialization()
> 
>         super.init(nibName: nibName, bundle: nibBundle)
>     }
>     
>     required init?(coder decoder: NSCoder) {
>         
>         (videoPlayer, videoPlayerLayer) = My.commonInitialization()
> 
>         super.init(coder: decoder)
>     }
>     
>     
>     private static func commonInitialization() -> (AVPlayer, AVPlayerLayer) {
>         
>         let player = AVPlayer(URL: NSURL(fileReferenceLiteral: "movie.mov"))
>         let layer = AVPlayerLayer(player: player)
>         
>         return (player,layer)
>     }
> }
> 
> It is not perfect, but good enough for me.  I usually use this when I have 
> more than one designated initializer and they share a significant amount of 
> code. I usually also have input parameters for this commonInitialization 
> static or class method. I make it a class method when I anticipate 
> subclassing of the class.
> 
> Side Note: As you see, I typically define a couple of private type aliases 
> (Usually `I` and/or `My`) to help with readability of code involving static 
> members.
> 
>> On Apr 27, 2016, at 2:52 PM, Shannon Potter via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> Consider a relatively-common init pattern:
>> 
>> class SomeViewController: UIViewController {
>> 
>>    // MARK: Properties
>> 
>>    private var videoPlayer: AVPlayer
>>    private var videoPlayerLayer: AVPlayerLayer
>> 
>>    // MARK: - Object Lifecycle
>> 
>>    override init(nibName: String?, bundle nibBundle: NSBundle?) {
>>        super.init(nibName: nibName, bundle: nibBundle)
>> 
>>        commonInitialization()
>>    }
>> 
>>    required init?(coder decoder: NSCoder) {
>>        super.init(coder: decoder)
>> 
>>        commonInitialization()
>>    }
>> 
>>    private func commonInitialization() {
>>        videoPlayer = AVPlayer(...)
>>        videoPlayerLayer = AVPlayerLayer(player: videoPlayer)
>>    }
>> 
>> }
>> 
>> This does not work. Both properties are non-optional, and the compiler 
>> complains that they are not initialized in either init method. It seems 
>> rather common to want a single point of contact regarding object 
>> initialization, regardless of the path taken to initialize that object. 
>> Ideally, objects could all be funneled to one designated initializer, but 
>> this isn’t always the case.
>> 
>> What are people’s thoughts about either a specialized function that is 
>> always called at the very end of each object’s lifecycle OR some sort of 
>> attribute for a function that hints that the compiler should follow it if 
>> called in an init function to check for property initialization?
>> 
>> func commonInit() {
>> 
>> }
>> 
>> or
>> 
>> @extend_init private func commonInitialization() {
>> 
>> }
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to