Czy możliwe jest dodawanie właściwości do obiektu Cel C w czasie wykonywania?Jak mogę dodać właściwości do obiektu w środowisku wykonawczym?
Odpowiedz
Jest możliwe, aby dodać właściwości formalnych do klasy poprzez class_addProperty()
:
BOOL class_addProperty(Class cls,
const char *name,
const objc_property_attribute_t *attributes,
unsigned int attributeCount)
Pierwsze dwa parametry są oczywiste. Trzeci parametr jest tablicą atrybutów właściwości, a każdy atrybut właściwości jest parą nazwa-wartość, która jest zgodna z Objective-C type encodings dla declared properties. Zauważ, że dokumentacja wciąż wspomina o ciągu oddzielonym przecinkami dla kodowania atrybutów właściwości. Każdy segment w łańcuchu oddzielonym przecinkiem jest reprezentowany przez jedną instancję objc_property_attribute_t
. Ponadto, objc_property_attribute_t
akceptuje nazwy klas oprócz ogólnego kodowania typu @
z id
.
Oto pierwszy projekt programu, który dynamicznie dodaje właściwość o nazwie name
do klasy, która ma już zmienną instancji o nazwie _privateName
:
#include <objc/runtime.h>
#import <Foundation/Foundation.h>
@interface SomeClass : NSObject {
NSString *_privateName;
}
@end
@implementation SomeClass
- (id)init {
self = [super init];
if (self) _privateName = @"Steve";
return self;
}
@end
NSString *nameGetter(id self, SEL _cmd) {
Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");
return object_getIvar(self, ivar);
}
void nameSetter(id self, SEL _cmd, NSString *newName) {
Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");
id oldName = object_getIvar(self, ivar);
if (oldName != newName) object_setIvar(self, ivar, [newName copy]);
}
int main(void) {
@autoreleasepool {
objc_property_attribute_t type = { "T", "@\"NSString\"" };
objc_property_attribute_t ownership = { "C", "" }; // C = copy
objc_property_attribute_t backingivar = { "V", "_privateName" };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
class_addProperty([SomeClass class], "name", attrs, 3);
class_addMethod([SomeClass class], @selector(name), (IMP)nameGetter, "@@:");
class_addMethod([SomeClass class], @selector(setName:), (IMP)nameSetter, "[email protected]:@");
id o = [SomeClass new];
NSLog(@"%@", [o name]);
[o setName:@"Jobs"];
NSLog(@"%@", [o name]);
}
}
Jego (przycinane) Wyjście:
Steve
Jobs
Metody getter i setter powinny być pisane ostrożniej, ale powinno to wystarczyć jako przykład dynamicznego dodawania formalnej właściwości w czasie wykonywania.
class_addProperty zwraca true, ale class_getInstanceVariable zawsze zwraca zero. Próbowałem wstawić nazwę właściwości zamiast nazwy ivar, ale wciąż nie miałem szczęścia. Jakiś pomysł, jaki może być problem? – Mercurial
@Barious, jak udało ci się wygłupiać? Mam na myśli, że [o name] powoduje błąd kompilacji "Brak znanej metody dla nazwy selektora". –
@HiteshSavaliya dawno temu (przed ARC) było to po prostu możliwe. w dzisiejszych czasach musielibyśmy przynajmniej zadeklarować selektor '-name'. – Michael
@ Właściwości - nie (np. Za pomocą składni punktowej itp.). Możesz jednak dodać pamięć masową przy użyciu powiązanych obiektów: How do I use objc_setAssociatedObject/objc_getAssociatedObject inside an object?.
Jeśli spojrzeć na protokole NSKeyValueCoding
, udokumentowany here, można zobaczyć, że nie jest to wiadomość o nazwie:
- (id)valueForUndefinedKey:(NSString *)key
Należy zastąpić tę metodę w celu zapewnienia niestandardowej wynik dla określonego niezdefiniowanej właściwości. Oczywiście zakłada to, że twoja klasa używa odpowiedniego protokołu.
Tego rodzaju podejście jest powszechnie stosowane w celu zapewnienia nieznanego zachowania dla klas (np. Selektora, który nie istnieje).
- 1. Rozmiar obiektu w środowisku wykonawczym
- 2. Jak dodać nowego użytkownika do Spring Security w środowisku wykonawczym
- 3. Określenie hierarchii klas obiektu w środowisku wykonawczym
- 4. Jak dodać nowe metadane idp wiosną SAML w środowisku wykonawczym
- 5. Jak mogę zmienić poziom rejestrowania pojedynczego rejestratora w środowisku wykonawczym?
- 6. Jak określić rzeczywisty typ obiektu w środowisku wykonawczym w C++;
- 7. Jak dodać nowy węzeł MvcSitemapProvider w środowisku wykonawczym
- 8. Dodawanie obrazu w środowisku wykonawczym
- 9. Jak mogę ustawić klasy javafx w środowisku wykonawczym?
- 10. Jaki jest ślad pamięci obiektu w środowisku wykonawczym w .NET?
- 11. Dynamiczne tworzenie i ustawianie elementów/właściwości klasy w środowisku wykonawczym
- 12. Architektura wtyczek do załadowania w środowisku wykonawczym
- 13. Jak zmienić AndroidManifest w środowisku wykonawczym?
- 14. Czy mogę rozróżnić wystąpienia typu typeclass w środowisku wykonawczym?
- 15. Jak konwertować typy w środowisku wykonawczym?
- 16. włączyć HeapDumpOnOutOfMemoryError w środowisku wykonawczym
- 17. Konfiguracja hibernacji w środowisku wykonawczym
- 18. Jak załadować obraz do WPF w środowisku wykonawczym?
- 19. Dodawanie klas jednostek dynamicznie w środowisku wykonawczym
- 20. Dodawanie adnotacji Java w środowisku wykonawczym
- 21. Android - Zmień układ fragmentów w środowisku wykonawczym
- 22. C# Utwórz i zmień klasę w środowisku wykonawczym
- 23. Jak przesłonić FetchType.EAGER, aby być leniwym w środowisku wykonawczym
- 24. Jak generować zasoby XML w środowisku wykonawczym w systemie Android?
- 25. Wywołanie elementu obiektu dynamicznego o nazwie zdefiniowanej w środowisku wykonawczym w ciągu znaków
- 26. Dodaj obraz do raportu Crystal w środowisku wykonawczym
- 27. Jak zmodyfikować PropertyGrid w środowisku wykonawczym (dodać/usunąć właściwość i typy dynamiczne/wyliczenia)?
- 28. Wykryj przyspieszenie sprzętowe w środowisku wykonawczym: Android
- 29. Java: Rozszerzanie klasy w środowisku wykonawczym
- 30. Znajdź zależne pakiety w środowisku Eclipse w środowisku wykonawczym
jeśli jest zgodny z protokołem KVC - jest to możliwe – Nekto
Co dokładnie masz na myśli według właściwości? Objective-C zadeklarowane właściwości? –
Mam na myśli @property – cfischer