2015-09-04 9 views
1

У меня возникли трудности с проверкой типа с типом протокола в Swift. У меня есть несколько протоколов (определенные в Obj-C рамки), и я пытаюсь, чтобы проверить их тип как так:Сравнение Swift Protocol

public func resolve(proto: Protocol!) -> NSObject { 

    // does not match when called with resolve(Foo) 
    if (proto is Foo) 
    { 
    return FooImpl(); 
    } 

    // other type checking here 

} 

Я попытался:

// Compile error: Expected member name or constructor call after type name 
if (proto === Foo) 

// Compile error: Expected member name or constructor call after type name 
if (proto == Foo) 

// Works, but seems hackish as it reverts to string comparison 
if (NSStringFromProtocol(proto) == NSStringFromProtocol(Foo)) 

Может ли это быть сделано без использования NSStringFromProtocol?

+0

Как определено foo? Я думаю, foo - это переменная класса, вы ее инициализировали? или у вас есть метод init()? (а не nscoder один) и есть foo, инициализированный там? (в методе init) – Zich

+0

Foo - это протокол, определенный только в объектно-c-структуре. –

ответ

4

Protocol - тип времени выполнения, а не объект. Вам нужно использовать функции runtime.

public func resolve(proto: Protocol) -> NSObject { 
    if protocol_isEqual(proto, Foo.self) { 
     return FooImpl() 
    } 

    // other type checking here 
} 

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

func resolve(proto: Foo.Type) -> NSObject { 
    return FooImpl() 
} 

func resolve(proto: Any) -> NSObject { 
    return DefaultIfYouNeedOne() 
} 

Swift будет выбрать лучшую перегрузку. Если у вас нет версии Any, это лучше, потому что тогда Swift не позволит вам передавать неожиданные типы resolve.

Но даже это часто предполагает, что вы делаете то, что, вероятно, не должно быть. Как правило, вы должны просто добавить init() в свой протокол, если вам нужно построить класс. Или создайте протокол Constructible для вещей, которые вы можете построить (или Resolvable или что вам нужно). Сосредоточьтесь на протоколах, а не на конкретных типах. Когда вы обнаружите, что выполняете большую проверку типов, вы, вероятно, сражаетесь с Swift. Возможно, вам придется совершить переход к ObjC, но не создавать больше этого. Почти ничего в Свифте никогда не вернется NSObject.

Несвязанное примечание: вы не должны использовать Protocol! в новых функциях. Вероятно, вы скопировали его из чего-то, что было автоматически импортировано из ObjC, которое не было проверено на отсутствие. Если вы знаете, что это не нуль, используйте тип. Если это может быть нуль, используйте опцию. Существует редкость для прохождения a !.

+0

Спасибо, фантастическая обратная связь, я не знал о функциях выполнения, это работает, и теперь мне нужно будет прочитать эту тему. Полностью согласен с вашими комментариями о проверке типов, этот пример немного придумал, чтобы проиллюстрировать вопрос :) –

Смежные вопросы