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 с каррированием, и довольно академично, если вы не любите исчисление типов.
У вас есть два варианта:
Объявите это действительно как
lazy var
вместоlet
, поэтому код не запускается во времяinit
но на самом деле при первом использовании.Объявите это без инициализации как Дополнительный. В зависимости от ограничений вашего дизайна это может быть либо громоздко, либо элегантно. Нет способа узнать. В любом случае, перед тем, как это потребуется, инициализируйте его значением, отличным от нуля. Легкое место, чтобы сделать это, если это
UIView
используется строго в раскадровке, чтобы инициализировать его вawakeFromNib()
,