Skip to content

Instantly share code, notes, and snippets.

@KentarouKanno
Last active April 9, 2017 11:20
Show Gist options
  • Save KentarouKanno/21d43d84b124ef144685 to your computer and use it in GitHub Desktop.
Save KentarouKanno/21d43d84b124ef144685 to your computer and use it in GitHub Desktop.
Initializer.md

Initializer

★ 以下はvalueが初期化されていないのでエラー

//=> Class 'InitClass' has no initializers
class InitClass {
    
    let value: Int
}

★ Default Initializer
イニシャライザでプロパティに値をセットする必要が無い場合に、Designated Initializerが実装されていない場合は以下のようにDefault Initializerが暗黙的に追加されます。

// 変数の初期化時に初期値を代入する
class InitClass {
    
    let value: Int = 0
}

// 変数の初期値がOptionalでnilで初期化される
class InitClass {
    
    let value: Int?
}

★ 指定イニシャライザ : designated initializer   インスタンスの初期化がすべて完了できるイニシャライザ

class InitClass {
    var value: Int
    
    // Designated initializer
    init() {
        value = 0
    }
}

var initClass = InitClass()

★ 簡易イニシャライザ : convenience initializer
イニシャライザの中で別のイニシャライザを呼ぶことができる

class InitClass {
    
    var value: Int = 0
    
    // Designated initializer
    init() {
        
    }
    
    // Convenience initializer
    convenience init(value: Int) {
        self.init()
        
        self.value = value
    }
}

// --- Usage ---

let designated = InitClass()
designated.value
//=> 0

let convenience = InitClass(value: 1)
convenience.value
//=> 1

★ 必須イニシャライザ : required initializer
継承先のサブクラスで、初期化処理をする時は必ず実装しなければならないイニシャライザ

class InitClass {
    
    var value: Int
    
    // Designated initializer
    init() {
        value = 0
    }
    
    // Required initializer
    required init(value: Int) {
        self.value = value
        
    }
}

class subInit: InitClass {
    
    // Override initializer
    override init() {
        super.init()
        
        value = 1
    }
    
    // Required initializer
    required init(value: Int) {
        fatalError("init(value:) has not been implemented")
    }
}
class InitClass {
    
    var value: Int
    
    // Designated initializer
    init() {
        value = 0
    }
    
    // Required initializer
    required init(value: Int) {
        self.value = value
        
    }
}

class SubInit: InitClass {
    
    // 初期化処理しない場合はRequired initializerも実装する必要が無い
}

// --- Usage ---

let subInit = SubInit()
subInit.value
//=> 0

let requiredInit = SubInit(value: 1)
requiredInit.value
//=> 1

★ 失敗のあるイニシャライザ : failable initializer
初期化が失敗した場合にnilを返すイニシャライザ

class InitClass {
    
    var value: Int = 0
    
    // Failable initializer
    init?(value: String) {
        guard let value = Int(value) else {
            return nil
        }
        
        self.value = value
    }
}

var initclass = InitClass(value: "a")
//=> nil

★ Memberwise Initializer (Structのみ)

Structureに対してイニシャライザが実装されていない時に
イニシャライザで値の代入が必要なプロパティがある場合にそれらを引数にとったイニシャライザが暗黙的に追加されます   これをMemberwise Initializerといいます。

struct Sample {
    
    let name: String = "Guest"
    let number: Int
    
}

let sample = Sample(number: 1)

★ Sub Classから呼び出せるのはSuper ClassのDesignated initializerのみ

class InitClass {
    
    var value: Int
    
    // Designated initializer
    init() {
        value = 0
    }
    
    // Convenience initializer
    convenience init(value: Int) {
        self.init()
        self.value = value
    }
}

class subInit: InitClass {
    
    // Override initializer
    override init() {
        super.init(value: 5) // Error
        // Must call a designated initializer of the superclass 'initClass'
        
    }
}

★ UIViewController

import UIKit

class CustomViewController: UIViewController {
    
    // Storyboardでの生成
    // ① required init
    
    // コードでの生成
    // ① override init
    // ② convenience init
    
    // コードでCustom Initializerでの生成
    // ① override init
    // ② Custom convenience init
    
    // Storyboardからの生成時に呼ばれる(Designated initializer)
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        
        print("required init")
        setup()
    }
    
    // コードでの生成時に呼ばれる① (Designated initializer)
    override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
        super.init(nibName: nil, bundle: nil)
        
        print("override init")
        setup()
    }
    
    // コードでの生成時に呼ばれる②(Convenience initializer)
    convenience init() {
        self.init(nibName: nil, bundle: nil)
        print("convenience init")
    }
    
    // Custom Initializer(Convenience initializer)
    convenience init(color: UIColor) {
        self.init(nibName: nil, bundle: nil)
        
        self.view.backgroundColor = color
        print("Custom convenience init")
    }
    
    func setup() {
        // init処理
        print("SetUp")
    }
    
    deinit {
        // 終了処理
    }
}

★ UIView

class CustomView: UIView {
    
    // Designated initializer
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    // Designated initializer
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    // Convenience initializer
    convenience init(bg_Color: UIColor) {
        self.init()
        self.backgroundColor = bg_Color
    }
}

★ UIViewのサブクラスを特定のInitializerでしか初期化をさせたくない場合

class CustomView: UIView {

    init(backColor: UIColor) {
        super.init(frame: CGRectZero)

        self.backgroundColor = backColor
    }

    @available(*, unavailable)
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

// init(backColor: UIColor)のみでしか初期化はできない

let vi = CustomView(backColor: UIColor.yellowColor())
vi.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
view.addSubview(vi)

★ 初期化アレンジ

class SuperClass {

    init(sender: String, recipient: String) {
        
    }
}

class SubClass: SuperClass {

    var content: String = ""
    
    init(content: String, sender: String, recipient: String) {
        self.content = content
        
        // スーパークラスの初期化を呼び出し
        super.init(sender: sender, recipient: recipient)
    }
    
    convenience init() {
        
        // 自身の初期化を呼び出し
        self.init(content: "")
    }
    
    convenience init(content: String) {
        
        // 自身の初期化を呼び出し
        self.init(content: content, sender: "Myself")
    }
    
    convenience init(content: String, sender: String) {
        
        // 自身の初期化を呼び出し
        self.init(content: content, sender: sender, recipient: sender)
    }
}

★ class

class InitClass {
    var value: Int
    
    init() {
        value = 0
    }
}

let obj = InitClass()

★ struct

struct InitStruct {
    var value: Int
    
    init() {
        value = 0
    }
}

let st = InitStruct()

★ enum

enum Size {
    case Small
    case Medium
    case Large
    
    // 引数なしコンストラクタ
    init() {
        self = .Small
    }
    
    // 引数ありコンストラクタ
    init(size: Size) {
        self = size
    }
}

var size1 = Size()
//=> Small

var size2 = Size(size: .Medium)
//=> Medium

★ 既存のinitializerを使用して拡張する

import UIKit

class ViewController: UIViewController {

    var fontArray = ["Zapfino","DBLCDTempBlack","MarkerFelt-Thin"]
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "text"
        label.font = UIFont(name: fontArray[0])
    }
}

extension UIFont {
    convenience init?(name: String) {
        self.init(name: name, size: 7)
    }
}

★ 初期化後にしかアクセスできなな変数

class B {
    var v1: Int!
    
    // こっちのが良い
    lazy var v2: Int = {
        fatalError("`\(#function)` is not initialized")
    }()
}

let b = B()
// fatal error: unexpectedly found nil while unwrapping an Optional value
//b.v1.description

// nil 入っちゃう
b.v1 = nil


// fatal error: `v2` is not initialized
//b.v2.description

// nil は入り得ない
//b.v2 = nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment