UPDATE для Swift 1.2
- Как RyanM отметил, есть изменения языка, которые удалили необходимость
@objc
ключевого слова.
Действительно, следующий простой пример теперь работает б/н @objc
ключевое слово:
protocol Ap {
func hello()
}
class A: Ap {
func hello() {
println("hello, world")
}
}
var a = A()
if (a as AnyObject) is Ap {
a.hello()
} else {
println("nope")
}
// hello, world
Кроме того, связь теперь только выглядит так:
protocol-conformance-1-2:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
@rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)
ORIGINAL:
Давайте посмотрим на пример. Обратите внимание, что я также использовал дополнительные вызовы (varName as AnyObject)
, иначе компилятор пожаловался 'is' test is always true
- так как он точно знал, что тип был во время компиляции.
import Foundation
protocol Swifty {
func s()
// protocol-conformance.swift:5:2: error: 'optional' can only be applied to members of an @objc protocol
// optional var a: Int { get }
// ^
/*
optional var a: Int { get }
*/
}
protocol SwiftyClass: class {
func scl()
// protocol-conformance.swift:13:2: error: 'optional' can only be applied to members of an @objc protocol
// optional var a: Int { get }
// ^
/*
optional var a: Int { get }
*/
}
@objc protocol SwiftyConformance {
func scon()
optional var a: Int { get }
}
class SwiftyOnly: Swifty {
func s() {
println("s")
}
}
class SwiftyClassOnly: SwiftyClass {
func scl() {
println("scl")
}
}
class SwiftyConformanceOnly: SwiftyConformance {
func scon() {
println("scon")
}
}
class SwiftyConformanceWithOptional: SwiftyConformance {
func scon() {
println("sconwo")
}
var a: Int {
get { return 1; }
}
}
println("swifty")
var swifty = SwiftyOnly()
//protocol-conformance.swift:49:26: error: cannot downcast from 'AnyObject' to [email protected] protocol type 'Swifty'
//if (swifty as AnyObject) is Swifty {
// ~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/*
if (swifty as AnyObject) is Swifty {
println("swifty is Swifty")
}
*/
// protocol-conformance.swift:47:34: error: cannot downcast from 'AnyObject' to [email protected] protocol type 'Swifty'
// if let s = (swifty as AnyObject) as? Swifty {
// ~~~~~~~~~~~~~~~~~~~~~^ ~~~~~~
/*
if let s = (swifty as AnyObject) as? Swifty {
s.s()
}
*/
println("")
println("swiftyClass")
var swiftyClass = SwiftyClassOnly()
//protocol-conformance.swift:61:31: error: cannot downcast from 'AnyObject' to [email protected] protocol type 'SwiftyClass'
/*
if (swiftyClass as AnyObject) is SwiftyClass {
println("swiftyClass is SwiftyClass")
}
*/
//protocol-conformance.swift:80:39: error: cannot downcast from 'AnyObject' to [email protected] protocol type 'SwiftyClass'
//if let s = (swiftyClass as AnyObject) as? SwiftyClass {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~^ ~~~~~~~~~~~
/*
if let s = (swiftyClass as AnyObject) as? SwiftyClass {
s.scl()
}
*/
println("")
println("swiftyConformanceOnly")
var swiftyConformanceOnly = SwiftyConformanceOnly()
if (swiftyConformanceOnly as AnyObject) is SwiftyConformance {
println("swiftyConformanceOnly is SwiftyConformance")
}
if let s = (swiftyConformanceOnly as AnyObject) as? SwiftyConformance {
s.scon()
if let a = s.a? {
println("a: \(a)")
}
}
println("")
println("swiftyConformanceWithOptional")
var swiftyConformanceWithOptional = SwiftyConformanceWithOptional()
if (swiftyConformanceWithOptional as AnyObject) is SwiftyConformance {
println("swiftyConformanceWithOptional is SwiftyConformance")
}
if let s = (swiftyConformanceWithOptional as AnyObject) as? SwiftyConformance {
s.scon()
if let a = s.a? {
println("a: \(a)")
}
}
println("")
... и (без раскомментируют тестовые случаи разбитого кода), выход:
swifty
swiftyClass
swiftyConformanceOnly
swiftyConformanceOnly is SwiftyConformance
scon
swiftyConformanceWithOptional
swiftyConformanceWithOptional is SwiftyConformance
sconwo
a: 1
Итак, простой ответ так же, как состояние Документов вам нужно @objc
для protocol conformance testing (и optionals).
В Swift objc - это всего лишь атрибут объявления, который обычно представляет собой намеки на компилятор или модифицирует способ генерации кода.
Но более длинный ответ затем задает вопрос: «но почему язык или время исполнения написаны таким образом?», И это сложнее обратиться; я предполагаю, что атрибут @objc
будет генерировать добросовестные ссылки Object/C Objective-C, а тестирование соответствия просто реализуется с использованием в течение времени выполнения.
Вы можете прокомментировать код в приведенном выше примере, который находится между/* и */по одному, и посмотреть, когда и где компилятор жалуется.
UPDATE: компилятор и компоновщик обновления
Если мы собираем выше: xcrun swiftc -sdk $(xcrun --show-sdk-path --sdk macosx) protocol-conformance.swift
и проверить, что она связана с с otool -L protocol-conformance
, мы видим
протокола-соответствия:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
@rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libswiftCoreGraphics.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libswiftDarwin.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libswiftDispatch.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libswiftFoundation.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libswiftObjectiveC.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libswiftSecurity.dylib (compatibility version 0.0.0, current version 0.0.0)
... поэтому я считаю, что более справедливо сказать, что для выполнения этих тестов соответствия вам необходимо взаимодействовать со средой Objective-C, но я не буду говорить, что вам нужно взаимодействовать с Objective-C (что для меня подразумевает некоторое количество код objc что вам придется задумчиво писать).
Посмотрите на очень простую программу протокола, используя:
protocol Ap {
func hello()
}
class A: Ap {
func hello() {
println("hello, world")
}
}
var a = A()
a.hello()
//$ otool -L hello-world
//hello-world:
// /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
// /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
// @rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)
... но если просто пытаться реализовать протокол @objc без каких-либо других изменений:
@objc protocol Ap {
func hello()
}
class A: Ap {
func hello() {
println("hello, world")
}
}
var a = A()
a.hello()
//$ xcrun swiftc -sdk $(xcrun --show-sdk-path --sdk macosx) hello-world.swift
//hello-world.swift:1:2: error: @objc attribute used without importing module 'Foundation'
//@objc protocol Ap {
// ^~~~
... и затем, если мы импортируем Фонд:
import Foundation
@objc protocol Ap {
func hello()
}
class A: Ap {
func hello() {
println("hello, world")
}
}
var a = A()
a.hello()
//$ otool -L hello-world
//hello-world:
// /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
// /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
// @rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)
// @rpath/libswiftCoreGraphics.dylib (compatibility version 0.0.0, current version 0.0.0)
// @rpath/libswiftDarwin.dylib (compatibility version 0.0.0, current version 0.0.0)
// @rpath/libswiftDispatch.dylib (compatibility version 0.0.0, current version 0.0.0)
// @rpath/libswiftFoundation.dylib (compatibility version 0.0.0, current version 0.0.0)
// @rpath/libswiftObjectiveC.dylib (compatibility version 0.0.0, current version 0.0.0)
// @rpath/libswiftSecurity.dylib (compatibility version 0.0.0, current version 0.0.0)
Я бы даже сказал, что стандартная библиотека Swift и среда исполнения абсолютно u отлаживает время выполнения Objective-C и ожидает доступа к базовым объектно-ориентированным объектам, таким как Foundation для основных функций.
Так TL; DR, что это потому, что протокол испытаний соответствия осуществляется в Objective-C время выполнения (не в Swift)? Другими словами - и это проверка соответствия протоколов crux - * * взаимодействует с Objective-C (даже если «я не»)? – orome
@raxacoricofallapatorius несколько - я обновил выше с моим мнением, но ответ в основном «да» - вам нужно взаимодействовать со временем выполнения Objective-C. – greymouser
@ RyanM: Предположительно неприемлемо в свете [(сообщается) изменений языка] (http://stackoverflow.com/a/29655235/656912). – orome