статические расширения протокола генерируют ошибку компилятора Illegal Instruction

Я прочитал Расширения, доступные в Swift, и интересовался, поддерживаются ли статические protocol extensions? Я знаю, что методы экземпляра можно использовать в protocol extension.

Я хотел создать протокол для своего репозитория вместе с реализацией этого репозитория:

Реализация репозитория

public protocol NoteRepositoryProtocol {
    func getAllNotes() -> [Note]
}

Обновлять

class NoteRepository : NoteRepositoryProtocol {
    func getAllNotes() -> [Note] {
        return [Note]()
    }
}

Затем, чтобы сохранить слабую связь в моем приложении, я хотел создать репозиторий через фабрику. Я пытался быть умным и прикрепил статический метод к своим протоколам вот так:

public extension NoteRepositoryProtocol {
    public static func createInstance() -> NoteRepositoryProtocol {
        return NoteRepository()
    }
}

Я знаю, что это можно сделать, если я опущу здесь ключевое слово static, но я действительно хотел, чтобы оно было статическим, чтобы я мог сделать это:

func test_note_repository_returns_a_valid_note_repository() {
    let repository = NoteRepositoryProtocol.createInstance()
}

Теперь, когда я хочу изменить реализацию своего репозитория, я могу сделать это, обновив метод фабрики расширения протокола. Другой альтернативой является создание реальной фабрики для обработки этого, но мне нравится идея фабричного метода, существующего в самом типе.

Когда я компилирую это, мне выдается следующая ошибка компилятора:

Команда не выполнена из-за сигнала: Недопустимая инструкция: 4

Вы не можете использовать статические методы в расширении протокола?

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

необязательное никогда не может быть нулевым

Протокол репозитория


person Johnathon Sullinger    schedule 20.06.2015    source источник
comment
Я посмотрю, как создать на нем ошибку.   -  person Sebastian Dressler    schedule 23.06.2015
comment
Однако строка, выполняющая проверку nil, не была ошибкой компилятора. Если я закомментирую это, я получаю ту же ошибку компилятора. Я дам вашему ответу шанс   -  person Johnathon Sullinger    schedule 23.06.2015


Ответы (2)


Как объясняется в Документация Apple:

public static func createInstance() -> NoteRepositoryProtocol? {
    return NoteRepository()
}
person Christian Dietrich    schedule 20.06.2015
comment
Это отлично решило мою проблему. Вы знаете техническую причину, по которой я вынужден возвращать необязательный параметр в этом сценарии? Нулевой чек в сторону. - person Johnathon Sullinger; 20.06.2015
comment
Хм, после перезапуска Xcode кажется, что сделать его необязательным не было проблемой. Я смог оставить свой код как есть и перекомпилировать без каких-либо проблем с помощью необязательного фабричного метода. Не уверен, что случилось с Xcode. - person Johnathon Sullinger; 20.06.2015
comment
если это не является необязательным, вы не можете проверить ноль. поэтому я предложил сделать это необязательным - person Johnathon Sullinger; 20.06.2015
comment
Хех, прости. Я внес изменения в свой код за одну ночь, одно из которых включало в себя преобразование этого протокола расширения в структуру. Когда я преобразовал его обратно в расширение протокола, сделать его необязательным или необязательным не решило эту ошибку компилятора. Я обновил свой OP, чтобы удалить проверку на ноль, так как это продолжает оставаться проблемой после удаления этой строки. - person Christian Dietrich; 20.06.2015
comment
предупреждение: инициализация неизменяемого значения 'репозиторий' никогда не использовалась; подумайте о замене присваиванием '_' или его удалении let repository = NoteRepositoryProtocol.createInstance () ~~~~ ^ ~~~~~~~~~ _ not existential UNREACHABLE выполняется в /Library/Caches/com.apple.xbs/ Исходники / swiftlang / swiftlang-700.0.38.1 / src / swift / lib / SILGen / SILGenExpr.cpp: 3311! 0 swift 0x0000000106760e0b llvm :: sys :: PrintStackTrace (__ sFILE *) + 43 1 swift 0x000000010676154b SignalHandler (int) + 379 2 libsystem_platform.dylib 0x00007fff9440ef1a _sigtramp + 26 3 swift 0100000001 + 010102106 : llvm_unreachable_internal (char const *, char const *, unsigned int) + 481 6 swift 0x00000001049b503c swift :: Lowering :: SILGenFunction :: emitOpenExistentialImpl (swift :: OpenExistentialExpr *, llvm :: function_ref) + 2588 7 swift :: 0x00000001049 :: RValue swift :: Lowering :: SILGenFunction :: emitOpenExistential (swift :: OpenExistentialExpr *, (анонимное пространство имен) :: RValueEmitter :: visitOpenExistentialExpr (swift :: OpenExistentialExpr *, swift :: Lowering :: SGFContext) :: $ _ 0) + 65 8 swift 0x00000001049b6f00 swift :: ASTVisitor ‹( анонимное пространство имен) :: RValueEmitter, swift :: Lowering :: RValue, void, void, void, void, void, swift :: Lowering :: SGFContext> :: visit (swift :: Expr *, swift :: Lowering :: SGFContext ) + 4864 9 swift 0x00000001049af49f swift :: Lowering :: SILGenFunction :: emitExprInto (swift :: Expr *, swift :: Lowering :: Initialization *) + 303 10 swift 0x00000001049a0dd8 swift :: Lowering :: SILGenFunction :: visitPatternBindingDecl (swift: : PatternBindingDecl *) + 232 11 swift 0x0000000104a021fa swift :: ASTVisitor ‹(анонимное пространство имен) :: StmtEmitter, void, void, void, void, void, void> :: visit (swift :: Stmt *) + 362 12 swift 0x0000000104a02085 swift :: Lowering :: SILGenFunction :: emitStmt (swift :: Stmt *) + 21 13 swift 0x00000001049ca136 swift :: Lowering :: SILGenFunction :: emitFunction (swift :: FuncDecl *) + 390 14 swift 0x000000010496d3ed swift :: Lowering :: SILGenModule :: emitFunction (swift :: FuncDecl *) + 253 15 быстрых 0x0000000104a0833c (анонимное пространство имен) :: SILGenType :: emitType () + 956 16 swift 0x0000000104a07ede swift :: Lowering :: SILGenModule :: visitNominalTypeDecl (swift :: NominalTypeDedule SilenceFile *) (swift :: SourceFile *, unsigned int) + 571 18 swift 0x000000010497106f swift :: SILModule :: constructSIL (swift :: ModuleDecl *, swift :: SILOptions &, swift :: FileUnit *, llvm :: Optional, bool, bool) + 703 19 swift 0x000000010497128b swift :: performSILGeneration (swift :: FileUnit &, swift :: SILOptions &, llvm :: Optional, bool) + 123 20 swift 0x000000010477a691 performCompile (swift :: CompilerInstance &, swift :: CompilerRenvocation &, llvm + 9153 21 swift 0x00000001047780b3 frontend_main (llvm :: ArrayRef, char const *, void *) + 2515 22 swift 0x000000010477428f main + 1983 23 libdyld.dylib 0x00007fff934fb5c9 start + 1 24 libdyld.dylib 0x0000000000000048 start + 1823492736 - person Johnathon Sullinger; 20.06.2015

Протоколы сами по себе не реализуют никаких функций. Тем не менее, любой созданный вами протокол станет полноценным типом для использования в вашем коде.

Следовательно, вы не можете напрямую вызывать статические методы протокола.

Мне это кажется ошибкой.

person Alejandro Hernández    schedule 22.11.2016