Como posso obter uma lista (na forma de um NSArray
ou NSDictionary
) de propriedades de um determinado objeto em Objective-C?
Imagine o seguinte cenário: Eu defini uma classe pai que apenas se estende NSObject
, que contém um NSString
, um BOOL
e um NSData
objeto como propriedades. Então, eu tenho várias classes que estendem essa classe pai, adicionando muitas propriedades diferentes a cada uma.
Existe alguma maneira de implementar um método de instância na classe pai que atravessa todo o objeto e retorna, digamos, um NSArray
de cada uma das propriedades da classe (filha), uma vez NSStrings
que não estão na classe pai, para que eu possa usá-los posteriormente NSString
para KVC?
[NSString stringWithCString:]
é substituído em favor de[NSString stringWithCString:encoding:]
.A resposta de @boliva é boa, mas precisa de um pouco mais para lidar com primitivos, como int, long, float, double, etc.
Eu construí dele para adicionar essa funcionalidade.
fonte
#import <Foundation/Foundation.h>
no início do arquivo .h?A resposta de @ orange80 tem um problema: na verdade, nem sempre termina a string com 0s. Isso pode levar a resultados inesperados, como travar ao tentar convertê-lo para UTF8 (na verdade, tive um crashbug muito chato só por causa disso. Foi divertido depurá-lo ^^). Corrigi-lo obtendo realmente um NSString do atributo e, em seguida, chamando cStringUsingEncoding :. Isso funciona como um encanto agora. (Também funciona com ARC, pelo menos para mim)
Portanto, esta é minha versão do código agora:
fonte
Quando tentei com o iOS 3.2, a função getPropertyType não funciona bem com a descrição da propriedade. Encontrei um exemplo na documentação do iOS: "Guia de programação em tempo de execução Objective-C: propriedades declaradas".
Aqui está um código revisado para a lista de propriedades no iOS 3.2:
fonte
Descobri que a solução do boliva funciona bem no simulador, mas no dispositivo a substring de comprimento fixo causa problemas. Eu escrevi uma solução mais amigável para o Objective-C para esse problema que funciona no dispositivo. Na minha versão, eu converto a C-String dos atributos em um NSString e executo operações de string nela para obter uma substring apenas com a descrição do tipo.
fonte
Esta implementação funciona com tipos de objeto Objective-C e primitivos C. É compatível com iOS 8. Esta classe fornece três métodos de classe:
Retorna um dicionário de todas as propriedades visíveis de um objeto, incluindo aquelas de todas as suas superclasses.
Retorna um dicionário de todas as propriedades visíveis de uma classe, incluindo aquelas de todas as suas superclasses.
Retorna um dicionário de todas as propriedades visíveis que são específicas de uma subclasse. Propriedades para suas superclasses não são incluídas.
Um exemplo útil do uso desses métodos é copiar um objeto para uma instância de subclasse em Objective-C sem ter que especificar as propriedades em um método de cópia . Partes desta resposta são baseadas em outras respostas a esta pergunta, mas fornece uma interface mais limpa para a funcionalidade desejada.
Cabeçalho:
Implementação:
fonte
Se alguém também precisa obter as propriedades herdadas das classes pai (como eu fiz), aqui estão algumas modificações no código " orange80 " para torná-lo recursivo:
fonte
A palavra "atributos" é um pouco confusa. Você quer dizer variáveis de instância, propriedades, métodos que se parecem com acessores?
A resposta a todas as três é "sim, mas não é muito fácil". A API de tempo de execução Objective-C inclui funções para obter a lista ivar, lista de métodos ou lista de propriedades para uma classe (por exemplo,
class_copyPropertyList()
) e, em seguida, uma função correspondente para cada tipo para obter o nome de um item na lista (por exemplo,property_getName()
).Resumindo, pode ser muito trabalhoso acertar, ou pelo menos muito mais do que a maioria das pessoas gostaria de fazer para o que normalmente é um recurso realmente trivial.
Alternativamente, você pode simplesmente escrever um script Ruby / Python que apenas leia um arquivo de cabeçalho e procure por qualquer coisa que você considere "atributos" para a classe.
fonte
Consegui fazer com que a resposta de @ orange80 funcionasse COM ARC ATIVADO ... ... para o que eu queria - pelo menos ... mas não sem um pouco de tentativa e erro. Esperançosamente, esta informação adicional pode poupar alguém do sofrimento.
Salve as classes que ele descreve em sua resposta = como uma classe e em sua
AppDelegate.h
(ou qualquer outra), coloque#import PropertyUtil.h
. Então em seu ...método (ou qualquer outro)
…
O segredo é lançar a variável de instância de sua classe ( neste caso, minha classe é
Gist
, e minha instânciaGist
égist
) que você deseja consultar ... para NSObject ...(id)
, etc, não vai funcionar .. para vários, estranho , razões esotéricas. Isso lhe dará alguma saída como ...Para todos os descarados / TOC da Apple se gabando da introspecção "espantosa" "do ObjC ... Eles certamente não tornam muito fácil realizar este simples" olhar "" para si mesmo "," por assim dizer "..
Se você realmente quer ficar louco .. confira .. class-dump , que é uma maneira absurdamente insana de espiar nos cabeçalhos das classes de QUALQUER executável, etc ... Fornece uma visão VERBOSA de suas classes ... que eu, pessoalmente, ache verdadeiramente útil - em muitas, muitas circunstâncias. na verdade é por isso que comecei a buscar uma solução para a questão do OP. aqui estão alguns dos parâmetros de uso .. divirta-se!
fonte
Você tem três feitiços mágicos
O seguinte código pode ajudá-lo.
fonte
Eu estava usando a função boliva fornecida, mas aparentemente ela parou de funcionar com o iOS 7. Agora, em vez de const char * getPropertyType (propriedade objc_property_t), pode-se usar apenas o seguinte:
fonte
Para espectadores do Swift, você pode obter essa funcionalidade utilizando a
Encodable
funcionalidade. Vou explicar como:Adapte seu objeto ao
Encodable
protocoloCrie uma extensão para
Encodable
fornecertoDictionary
funcionalidadeChame
toDictionary
sua instância de objeto ekeys
propriedade de acesso .Voila! Acesse suas propriedades da seguinte forma:
fonte
Essas respostas são úteis, mas preciso mais disso. Tudo o que quero fazer é verificar se o tipo de classe de uma propriedade é igual ao de um objeto existente. Todos os códigos acima não são capazes de fazer isso, porque: Para obter o nome da classe de um objeto, object_getClassName () retorna textos como estes:
Mas se invocar getPropertyType (...) do código de amostra acima, com 4 estruturas objc_property_t de propriedades de uma classe definida desta forma:
ele retorna strings respectivamente como a seguir:
Portanto, não é possível determinar se um NSObject é capaz de ser o valor de uma propriedade da classe. Como fazer isso então?
Aqui está meu código de amostra completo (a função getPropertyType (...) é a mesma acima):
fonte