Как я могу получить список (в форме NSArray
или NSDictionary
) свойств данного объекта в Objective-C?
Представьте себе следующий сценарий: Я определил родительский класс , который только расширяет NSObject
, что держит NSString
, BOOL
и в NSData
объект как свойства. Затем у меня есть несколько классов, которые расширяют этот родительский класс, добавляя к каждому множество различных свойств.
Могу ли я реализовать метод экземпляра в родительском классе, который проходит через весь объект и возвращает, скажем, NSArray
каждое из свойств (дочернего) класса, поскольку NSStrings
они не находятся в родительском классе, поэтому я могу позже использовать их NSString
для KVC?
[NSString stringWithCString:]
устарел в пользу[NSString stringWithCString:encoding:]
.Ответ @boliva хорош, но для обработки примитивов, таких как int, long, float, double и т. д., требуется немного больше.
Я построил его, чтобы добавить эту функциональность.
источник
#import <Foundation/Foundation.h>
разместить вверху файла .h?Ответ @ orange80 имеет одну проблему: на самом деле он не всегда завершает строку нулями. Это может привести к неожиданным результатам, таким как сбой при попытке преобразовать его в UTF8 (на самом деле у меня был довольно неприятный сбой только из-за этого. Было весело его отлаживать ^^). Я исправил это, фактически получив NSString из атрибута, а затем вызвав cStringUsingEncoding :. Теперь это работает как шарм. (Также работает с ARC, по крайней мере, для меня)
Итак, это моя версия кода:
источник
Когда я пробовал использовать iOS 3.2, функция getPropertyType не работает с описанием свойства. Я нашел пример из документации iOS: «Руководство по программированию времени выполнения Objective-C: объявленные свойства».
Вот исправленный код для списка свойств в iOS 3.2:
источник
Я обнаружил, что решение boliva отлично работает в симуляторе, но на устройстве подстрока фиксированной длины вызывает проблемы. Я написал более дружественное к Objective-C решение этой проблемы, которое работает на устройстве. В своей версии я конвертирую C-строку атрибутов в NSString и выполняю над ней строковые операции, чтобы получить подстроку только с описанием типа.
источник
Эта реализация работает как с типами объектов Objective-C, так и с примитивами C. Он совместим с iOS 8. Этот класс предоставляет три метода класса:
Возвращает словарь всех видимых свойств объекта, включая свойства всех его суперклассов.
Возвращает словарь всех видимых свойств класса, включая свойства всех его суперклассов.
Возвращает словарь всех видимых свойств, относящихся к подклассу. Свойства его суперклассов не включены.
Одним из полезных примеров использования этих методов является копирование объекта в экземпляр подкласса в Objective-C без необходимости указывать свойства в методе копирования . Части этого ответа основаны на других ответах на этот вопрос, но он обеспечивает более чистый интерфейс для желаемой функциональности.
Заголовок:
Реализация:
источник
Если кому-то также необходимо получить свойства, унаследованные от родительских классов (как это сделал я), вот некоторые модификации кода " orange80 ", чтобы сделать его рекурсивным:
источник
Слово «атрибуты» немного расплывчато. Вы имеете в виду переменные экземпляра, свойства, методы, которые выглядят как аксессоры?
Ответ на все три вопроса - «да, но это не очень просто». Objective-C во время выполнения API , включает в себя функцию , чтобы получить список ИВАР, список методов или список свойств для класса (например,
class_copyPropertyList()
), а затем соответствующая функция для каждого типа , чтобы получить имя элемента в списке (например,property_getName()
).В целом, чтобы сделать это правильно, может потребоваться много работы или, по крайней мере, намного больше, чем хотелось бы большинству людей для того, что обычно сводится к действительно тривиальной функции.
В качестве альтернативы вы можете просто написать сценарий Ruby / Python, который просто читает файл заголовка и ищет все, что вы считаете «атрибутами» для класса.
источник
Я смог получить ответ @ orange80 для работы С ARC ENABLED …… для того, что я хотел - по крайней мере… но не без проб и ошибок. Надеюсь, эта дополнительная информация избавит кого-то от горя.
Сохраните те классы, которые он описывает в своем ответе = как класс, и в свой
AppDelegate.h
(или что-то еще) поместите#import PropertyUtil.h
. Тогда в вашем ...метод (или что угодно)
…
Секрет в том, чтобы преобразовать переменную экземпляра вашего класса ( в данном случае мой класс есть
Gist
, а мой экземплярGist
естьgist
), который вы хотите запросить ... в NSObject ...(id)
и т. Д., Не будет сокращать его .. для различных, странных , эзотерические причины. Это даст вам такой результат…Несмотря на все беззастенчивое хвастовство Apple / ОКР по поводу самоанализа ObjC "удивительными шарами" ... Они определенно не облегчают выполнение этого простого "взгляда" "на себя", "так сказать" ..
Если вы действительно хотите сходить с ума … проверьте .. class-dump , который является ошеломляющим безумным способом заглянуть в заголовки классов ЛЮБОГО исполняемого файла и т. Д. Он обеспечивает ГЛАГОЛЬНЫЙ взгляд на ваши классы… что я, лично я считаю действительно полезным - во многих, многих обстоятельствах. именно поэтому я начал искать решение вопроса ОП. вот некоторые параметры использования .. наслаждайтесь!
источник
У вас есть три магических заклинания
Следующий фрагмент кода может вам помочь.
источник
Я использовал предоставленную функцию boliva, но, видимо, она перестала работать с iOS 7. Итак, теперь вместо static const char * getPropertyType (свойство objc_property_t) можно просто использовать следующее:
источник
Для наблюдателей Swift вы можете получить эту функциональность, используя ее
Encodable
. Я объясню как:Приведите свой объект в соответствие с
Encodable
протоколомСоздать расширение для
Encodable
обеспеченияtoDictionary
функциональностиВызовите
toDictionary
свой экземпляр объекта и получите доступ кkeys
свойству.Вуаля! Доступ к своим свойствам можно получить так:
источник
Эти ответы полезны, но мне нужно от них большего. Все, что я хочу сделать, это проверить, совпадает ли тип класса свойства с типом класса существующего объекта. Все приведенные выше коды не могут этого сделать, потому что: Чтобы получить имя класса объекта, object_getClassName () возвращает такие тексты:
Но если вызвать getPropertyType (...) из приведенного выше примера кода, с 4 структурами objc_property_t свойств класса, определенного следующим образом:
он возвращает строки соответственно следующим образом:
Таким образом, невозможно определить, может ли NSObject быть значением одного свойства класса. Как тогда это сделать?
Вот мой полный пример кода (функция getPropertyType (...) такая же, как и выше):
источник