The objc_property_t * class_copy PropertyList (Class cls, unsigned int * outCount) function is a function in runtime that copies a list of attributes of a class object and returns an array of values of type objc_property_t*. You can then traverse the array to extract each attribute value. Almost every dictionary-to-model framework needs this function.
- (NSDictionary *)properties_aps { NSMutableDictionary *props = [NSMutableDictionary dictionary]; unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList([self class], &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; NSString *propertyName = [[[NSString alloc] initWithCString:property_getName(property)] autorelease]; id propertyValue = [self valueForKey:(NSString *)propertyName]; if (propertyValue) [props setObject:propertyValue forKey:propertyName]; } free(properties); return props; }
This code contains functions to take attributes:
objc_property_t *properties = class_copyPropertyList([self class], &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; }
An array of properties of type objc_property_t* is obtained by taking out the subscript and obtaining an array element of type objc_property_t.
This expression suddenly feels a little puzzled, because if we replace objc_property_t with int:
int main(int argc, const char * argv[]) { int *arr = {1,2,3}; arr[1] = 10; int a = arr[1]; NSLog(@"%d", a); return 0; }
In C, the essence of arrays is po int er plus offset, so when we assign arr[1], it is equivalent to 8 bit offset to arr. However, we do not open up memory space for the following address, which naturally causes EXC_BAD_ACCESS error.
So how to write a foo array variable of type * type in runtime and get an array element of type with foo[1]?
So we have to analyse how the above int is written incorrectly. Because when initializing int *arr, there is no sizeof(int)*count memory space.
The reason why it can be written as int arr[3] is that the essence of C language array is pointer plus offset. An int pointer is initialized, and a 3*sizeof(int) memory space is given, returning a pointer arr. So we can do this step manually:
typedef int integer; typedef integer * integer_pointer; integer_pointer * addIntegerToArr(integer_pointer p, ...) { integer_pointer *result = nil; if (p) { va_list args; int count = 1; integer_pointer current; va_start(args, p); while ((current = va_arg(args, integer_pointer))) { ++count; } va_end(args); result = (integer_pointer *)malloc((count) * sizeof(integer_pointer)); result[0] = p; va_start(args, p); current = va_arg(args, integer_pointer); for (int i = 1; i < count; i++) { result[i] = current; } va_end(args); } return (integer_pointer *)result; } int main(int argc, const char * argv[]) { integer a = 10; integer b = 11; integer_pointer pa = &a; integer_pointer pb = &b; integer_pointer *r = addIntegerToArr(pa, pb); integer_pointer num = r[1]; NSLog(@"%d", *num); return 0; }
The key code is result = integer_pointer*) malloc ((count)* sizeof (integer_pointer);, so we open up a memory space and get an integer_pointer* type pointer, so we can manipulate the integer_pointer in this space by offsetting the pointer. Variables.
The reason why result looks like an array can be written as result[i] is because of the above reasons.
So remember that arrays in C are essentially pointer plus offset.
Although we are iOS developers, after all, C language can not be put aside, idle can imitate many C language features in runtime to achieve some language level learning. Although the above-mentioned content is too naive for a master who is really proficient in C/C++, the process of thinking is still very interesting. In addition, in the above exercise, I also learned the content of variable parameters.
It's not too technical, so it's just idle.
Welcome to my blog for more information http://suntao.me