init?(coder aDecoder: NSCoder)

Mast call a designated initializer of the superclass 
‘required’ initializer ‘init(coder:)’ must be provided by subclass of

如果你要用 Swift创建一个实现了 NSCoding协议的类(UIView,UIViewController)的子类的时候,你就会发现一种很尴尬的情况,required init?(coder aDecoder: NSCoder), 还是必须实现的,然而你可能并不知道这是什么鬼,也不知道有什么卵用,你可能只是简单的知道他是 NSCoding 的协议方法而已.

  • Swift中,如果你要重写父类的构造器,并且父类实现了 NSCoding,那么在子类中你也必须实现这个构造器

    required init?(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
        }
    • 1
    • 2
    • 3
  • 所以你觉得万事大吉了,对不起,你错了。Swift在类初始化时,出于对安全性的考虑,对类的所有内部属性必须全部被初始化(通俗一点就是分配一个默认值),否则编译器报错,next eg.

    class ViewController: UIViewController {  
     var name: String
     var age : Int
     init() {
       name = "Paul"
       age = 24
       super.init(nibName: nil, bundle:nil)
     }
     required init(coder: NSCoder) {
       super.init(coder: coder)
     }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 有些人说话了,谁说了一定要初始化,比如 var age : Int? 就不需要在super.init()之前必须初始化,?是可选型符号,这种写法规定你的 age属性是个可选型,什么是可选型,可选型是指,在你没有赋值的情况下默认赋值为nil,所以即使 age定义的时候没有初始化,但是它已经被初始化了(nil 表示空值,和OC中的空对象区别,例如 Swift 中是不能通过 age=nil 来释放一个对象的),
  • 但是,如果你想要实现一个自定义的构造器,怎么做,我猜可能是这样

    class ViewController: UIViewController {  
        let name: String
        init() {
          name = "Paul"
          super.init(nibName: nil, bundle:nil)
         }
         init(name aName : String) {
            name = "Paul"
            super.init(nibName: nil, bundle:nil)
         }
        required init(coder: NSCoder) {
            name = "Paul"   \\ 索性都写上,
            super.init(coder: coder)
         }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    如果我有10个,100个属性呢?耗时间,那干脆想oc一样,写一个赋值的方法

    class ViewController: UIViewController {  
        let name: String
        init() {
          setup()
          super.init(nibName: nil, bundle:nil)
         }
         init(name aName : String) {
            setup()
            super.init(nibName: nil, bundle:nil)
         }
        required init(coder: NSCoder) {
            setup()
            super.init(coder: coder)
         }
         func setup() {
            name = "Paul"
            age = 25
         }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这样一来有一百个也无妨,想法很不错,有见地,但是很可惜,编译未通过,(举个例子,对象好比蛋里面的鸡,属性是肌肉,方法是鸡翅、鸡爪等),在super.init之前(蛋孵化之前),方法也同样没有被初始化(鸡都没有孵出来,你就想烤鸡翅了?)

  • 废话说了这么多,到底怎么解决呢,别着急,

    class ViewController: UIViewController {  
        let name: String
        // 自定义的构造器
        init(_ coder: NSCoder? = nil) {
            name = "Paul"
            if let coder = coder {
                super.init(coder: coder)!
            } else {
                super.init(nibName: nil, bundle:nil)
            }
        }
        required convenience init(coder: NSCoder) {
            self.init(coder)
        }
        // 下面这句可省去
        override convenience init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
            self.init(nil)
        }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    像这样,我们在我们自定义的构造器 init(_ coder: NSCoder? = nil) 中添加了一个可选型的 NSCoding 的参数,默认是nil,所以我们像之前那样不用任何参数调用init(nil)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值