[swift-evolution] Extending init checks for property initialization

Basem Emara contact at basememara.com
Sat Apr 30 13:30:54 CDT 2016


Hey Hooman, that’s very elegant. I didn’t think of it like that and will definitely use, thx!

Though wouldn’t “defer init()” take it a step further: 1) reduce redundant boilerplate 2) prevent forgetting/bugs and 3) smaller memory allocation footprint? It also fits well with the existing Swift 2 “defer” keyword used in functions. Here’s what your sample would look like:

import UIKit
import AVFoundation

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)
    }
    
    required init?(coder decoder: NSCoder) {
        
        super.init(coder: decoder)
    }
   
    defer init() {
        videoPlayer = AVPlayer(URL: NSURL(fileReferenceLiteral: "movie.mov"))
        videoPlayerLayer = AVPlayerLayer(player: player)
    }
}

> On Apr 30, 2016, at 2:18 PM, Hooman Mehr via swift-evolution <swift-evolution at swift.org> 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 <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> 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
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160430/8e10f418/attachment.html>


More information about the swift-evolution mailing list