Вы действительно можете вызвать какой-либо метод Objective-C для AnyObject?

#swift

#swift

Вопрос:

Согласно iBook «Использование Swift с Cocoa и Objective-C» (около Loc 9) относительно id совместимости:

Вы также можете вызвать любой метод Objective-C и получить доступ к любому свойству без приведения к более конкретному типу класса.

Пример, приведенный в книге (показан ниже), не компилируется, что, по-видимому, противоречит приведенному выше утверждению. Согласно книге, последняя строка ниже не должна выполняться, потому length что свойство не существует для NSDate объекта.

 var myObject: AnyObject = UITableViewCell()
myObject = NSDate()
let myLength = myObject.length?
  

Вместо этого не удается выполнить компиляцию с ошибкой «Не удалось найти перегрузку для «длины», которая принимает предоставленные аргументы» в последней строке.

Это ошибка, опечатка или утверждение о вызове любого метода Objective-C неверно?

Ответ №1:

ошибка компилятора говорит length , что это функция, и вы вызываете ее с неверными аргументами

вы можете сделать myObject.length?() , который возвращает nil

также myObject.count? выдаст вам nil ошибку компиляции

  xcrun swift
Welcome to Swift!  Type :help for assistance.
  1> import Cocoa
  2> var obj : AnyObject = NSDate()
obj: __NSDate = 2014-06-25 13:02:43 NZST
  3> obj.length?()
$R5: Int? = nil
  4> obj.count?
$R6: Int? = nil
  5> obj = NSArray()
  6> obj.length?()
$R8: Int? = nil
  7> obj.count?
$R9: Int? = 0
  8>
  

Я думаю, что компилятор выполнял поиск по всем вызываемым методам и свойствам length , он обнаружил, что какой-то класс предоставляет length() , но класс не предоставляет length , отсюда и сообщение об ошибке. Точно так же, как при вызове [obj nonexistmethod] в ObjC, компилятор выдаст сообщение об ошибке « nonexistmethod не существует», даже если вы вызываете его для id типа object

Это то, что произошло, если вы попытаетесь вызвать несуществующий метод в Swift

  14> obj.notexist?
<REPL>:14:1: error: 'AnyObject' does not have a member named 'notexist'
obj.notexist?
^   ~~~~~~~~

 14> obj.notexist?()

<REPL>:14:1: error: 'AnyObject' does not have a member named 'notexist()'
obj.notexist?()
^   ~~~~~~~~
  

Комментарии:

1. Но есть много классов, которые принимают length , а не length() . Например, var data = NSMutableData(); let otherLength = data.length будет компилироваться и работать.

2. @JefferyRPrice возможно, это ошибка компилятора (или дефект языка). возможная причина, по которой length for NSData не найден, потому что это не свойство ObjC, а обычный метод -[length] , который имеет смысл переводить length() вместо length

3. Я могу в это поверить, но будет ли это квалифицироваться как ошибка, опечатка или подразумевать, что утверждение о вызове любого метода Objective-C неверно? Кроме того, в документации говорится, что объявление Obj-C для длины равно @property(readonly) NSUInteger length .