#objective-c #nsobject #nsinvocation
#objective-c #nsobject #nsinvocation
Вопрос:
Я пишу клон OpenStruct на Objective-C, используя forwardInvocation:. Однако компилятор, по-видимому, не знает о пересылке во время компиляции. Компиляция с помощью ARC выдает мне массу предупреждений.
Код с открытым исходным кодом и доступен на Github, но в настоящее время скомпилирован с помощью -fno-objc-arc. Если кто-нибудь может взглянуть на то, как я мог бы сделать этот ARC совместимым, я был бы очень признателен.
Комментарии:
1. Было бы полезно, если бы вы опубликовали хотя бы одну из ошибок и соответствующий код, с которым у компилятора возникла проблема.
2. Невозможно сделать то, что вы пытаетесь сделать. Компилятор должен знать сигнатуры методов во время компиляции и будет жаловаться, если он их не знает.
Ответ №1:
Я попробовал этот код:
OpenStruct *myStruct = [[OpenStruct alloc] initWithDictionary:myDictionary];
NSLog(@"%@ says %@", @"Cow", [myStruct cowSound]);
Я получаю предупреждения или ошибки с ARC и без него, с LLVM 3.0 или LLVM GCC 4.2. Я думаю, вы неправильно поняли, что forwardInvocation: по-прежнему требует, чтобы метод был объявлен на некотором уровне, хотя бы в категории (@interface) класса, которому вы отправляете сообщение.
Например, когда вы делаете:
[someObject doSomething];
Тогда это всегда будет генерировать по крайней мере предупреждение («SomeObject может не отвечать на doSomething»), если doSomething нигде не объявлен, независимо от того, реализует класс SomeObject forwardInvocation или нет. Как вы заметили, компилятор действительно не знает о пересылке, и он также не может полагаться на то, что ваша реализация forwardInvocation гарантирует доставку сообщений. В LLVM 3.0 с ARC или без него это могло быть изменено, чтобы вместо этого генерировать ошибку, потому что целью разработки ARC была ошибка в сторону большего количества ошибок компилятора, а не проблем во время выполнения.
Теперь вы все еще можете отправлять сообщения объекту, который не реализует метод. Например, с помощью метода Objective-C во время выполнения objc_msgSend или через NSInvocation. Но это аннулирует простой в использовании интерфейс, который вы планировали создать.
Кстати, ваш пример использования для OpenStruct на самом деле не объясняет, почему доступ к динамической структуре через обмен сообщениями проще, чем к простым средствам доступа, таким как [struct getValueForKey:@»moo»]; … если вы подумаете об этом, то [struct moo] дает пользователям мало или вообще не дает преимуществ по сравнению с первым подходом. Метод «moo» является динамическим в любом случае (строка или перенаправленное сообщение), и опечатка не будет обнаружена во время выполнения.
Комментарии:
1. Преимуществом было бы просто уменьшение размера кода. Я думаю, что это более важно. [звук коровы] сразу говорит о том, что вас интересует звук, который издает корова.
2. Конечно, но тогда вы могли бы просто написать класс Cow с помощью метода sound, верно? Или, еще лучше, класс Animal, который реализует метод sound, а имя файла sound может быть задано при инициализации или через свойство. Все другие классы, такие как Cow, Frog, Pterodactyl, наследуются от Animal и могут впоследствии воспроизводить звук.
3. Вариант использования, о котором я думаю, предназначен для интерфейса с CMS. Содержимое будет управляться веб-приложением. Приложение iOS будет синхронизироваться с ним. Невозможно заранее определить все потенциальные поля в коде iOS, потому что они могут быть добавлены и удалены пользователем по желанию через веб-интерфейс. Использование словарей или кодирования ключ-значение является неуклюжим синтаксисом и требует много ввода по сравнению с использованием синтаксиса свойств.
4. Вы можете использовать синтаксис свойств (например,
myLabel.stringValue
) только со свойствами, которые определены с помощью@property
в файле заголовка. Итак, как указано выше,-(id)getObjectForKey:
, скорее всего, лучший выбор. Objective C чрезвычайно подробный. Обычно рекомендуется использовать лучшие практики языка, а не пытаться обойти их с помощью опасных взломов.5. Те же проблемы применимы и к альтернативам. Объекты в словарях не имеют проверки типа. Кодирование ключ-значение не имеет проверки типа. Являются ли они оба также «опасными взломами»?