Невозможно привести значение типа MyClass к MyDelegate. - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть класс, которому нужно установить компонент на self.Этот компонент требует, чтобы класс реализовал protocol MyDelegate .В конце концов, это терпит неудачу (SIGNAL SIGABRT).

// I need the class to be a NSObject for unrelated requirements 
class MyClass: NSObject {

// I force the compilation, but it then breaks apart at runtime anyway
 private let myComponent = 
 Component(requiresAnObjectofTypeMyDelegate: self as! MyDelegate) 
}

// in the same file 
 extension MyClass: MyDelegate {  
   func myUsefulDelegateCall() {
   } 
 }

Почему?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Проблема заключается в использовании self внутри хранимого свойства myComponent.Как правило, не разрешается раздавать self до завершения инициализации инициализатора всего объекта.Поэтому ваша проблема не имеет ничего общего с протоколами или расширениями.Более просто:

import Foundation


class Component {
    init(requiresAnObjectofTypeMyClass:MyClass) {
    }
}

// I need the class to be a NSObject for unrelated requirements 
class MyClass : NSObject {

    // I force the compilation, but it then breaks apart at runtime anyway
    private let  myComponent = 
        Component(requiresAnObjectofTypeMyClass : self as! MyClass)
}

let m = MyClass()

также дает сбой.

Если вы пропустите подкласс NSObject, вы получите ошибку компилятора:

использование неразрешенного идентификатораКомпонент 'self' (требуетAnObjectofTypeMyClass: self as! MyClass)

Это показывает проблему: вы не должны использовать self здесь.Я думаю, что это просто ошибка XCode;Xcode, кажется, игнорирует синтаксическую ошибку при создании подкласса NSObject.Приведение as! MyClass также является подсказкой о том, что мы ищем странный обходной путь, который, в конце концов, ставит Xcode на колени и вызывает сбой во время выполнения.

Чтобы обойти это, вы можете создать свойство lazy, которое будетбудет оцениваться после процесса инициализации и, следовательно, позволит self быть переданным в Component инициализатор:

private(set) lazy var  myComponent = Component(requiresAnObjectofTypeMyClass:self)

Здесь вам также не понадобится приведение.К сожалению, lazy let не разрешен в swift (и никто не знает почему), поэтому private(set) близок к его семантике.

Этот код легко перенести в пример протокола.

0 голосов
/ 03 декабря 2018

Тип приведения не требуется.Поскольку MyClass принимает MyDelegate, это равно также MyDelegate.

И лениво инициализирует свойство, чтобы можно было использовать self на верхнем уровне.на всех.

private lazy var myComponent = Component(requiresAnObjectofTypeMyDelegate: self) 
...