UIView, CMDeviceMotionHandler: unowned может применяться только к классам и типам протоколов, связанных с классом

Я создаю UIView, который слушает CMDeviceMotion События:

class MyView: UIView{


    private var motionManager = CMMotionManager()
    let motionQueue = NSOperationQueue()


    override func awakeFromNib() {
        self.setupView()
    }

    func setupView(){
        self.motionManager.deviceMotionUpdateInterval = 0.5
        self.motionManager.startDeviceMotionUpdatesUsingReferenceFrame(.XArbitraryZVertical, toQueue: self.motionQueue, withHandler: self.motionHandler)
    }

    // MARK: - CMDeviceMotionHandler

    let motionHandler : CMDeviceMotionHandler = {
        [unowned self] (motion,error) in
    }
}

Я хотел бы объявить мой CMDeviceMotionHandler закрытие как переменная-член, однако я получаю ошибку:

"unowned" может применяться только к классу и типам протокола, привязанного к классу, но не "MyView -> () -> MyView"

MyView это UIView который в свою очередь является классом, так что я не понимаю, почему он жалуется, что unowned не может быть применено.

Я искал другие вопросы с той же проблемой, но большинство из них касалось лениво вычисляемых переменных. Как решить эту ошибку для моего сценария?

1 ответ

Решение

Строка кода, на которой вы находитесь, фактически выполняется во время init функция. self недоступно, пока не будут инициализированы все сохраненные свойства. Вы находитесь в середине процесса.

Сообщение об ошибке довольно запутанно и бесполезно, потому что self в контексте инициализаторов свойств не является экземпляром MyView, но сложный мета-тип: функция-член класса, которая не привязана к своему экземпляру, но становится связанной и пригодной для использования, как только экземпляр передается в качестве первого аргумента. Это связано с функциями-членами, реализуемыми в Swift с каррированием, и довольно академично, если вы не любите исчисление типов.

У вас есть два варианта:

  1. Объявите это действительно как lazy var вместо let, поэтому код не запускается во время init но на самом деле при первом использовании.

  2. Объявите это без инициализации как Дополнительный. В зависимости от ограничений вашего дизайна это может быть либо громоздко, либо элегантно. Нет способа узнать. В любом случае, перед тем, как это потребуется, инициализируйте его значением, отличным от нуля. Легкое место, чтобы сделать это, если это UIView используется строго в раскадровке, чтобы инициализировать его в awakeFromNib(),

Другие вопросы по тегам