2010年5月7日星期五

Objective-C runtime

#import <objc/runtime.h>

#import <objc/message.h>

This is the first time we’ve worked with the Objective-C runtime directly. Although for most programming jobs there’s no need to dive down into the runtime, having access to the same functions that are used to implement Objective-C gives us an incredible amount of power. Let’s quickly run through what we’re doing here, but don’t feel like you have to grok this one the first time through.
First, we declare an int, which will hold the number of properties that managedObject has. Then we declare a pointer to an objc_property_t, which is a datatype that represents Objective-C 2.0 properties, and use a runtime function called class_copyPropertyList() to retrieve the list of pointers to the managedObject properties. This function also populates outCount with the number of properties.

unsigned int outCount; objc_property_t *propList =

class_copyPropertyList([self.managedObject class], &outCount); Next, we use a for loop to iterate over the properties:

for (int i=0; i < outCount; i++)

{

We grab a reference to the structure that points to one property in the list, and then get the property’s name as an NSString instance. We also get the property’s attributes, which are contained in a string. The format for the attribute string is documented in Apple’s Objective-C runtime documentation, but for our purposes, all we need to know

is that it contains (among other things) the class of the property.

We check to see if the attribute string contains @"NSSet":

if ([attrs rangeOfString:@"NSSet"].location != NSNotFound) {

If it does, we then retrieve the set and create an instance of NSMutableArray to keep track of the objects that need to be deleted. It is not safe to delete objects from a collection while we are iterating over it, so we’ll stick them in an array. Then, when we’re finished iterating, we’ll iterate through the array of objects that need to be deleted and remove them.

}

}

NSMutableSet *objects = [self.managedObject valueForKey:propName];

NSMutableArray *toDelete = [NSMutableArray array]; for (NSManagedObject *oneObject in objects) {

if ([oneObject isDeleted]) [toDelete addObject:oneObject];

} for (NSManagedObject *oneObject in toDelete) {

}

[objects removeObject:oneObject]; NSError *error; if (![self.managedObject.managedObjectContext save:&error])

NSLog(@"Error saving: %@", [error localizedDescription]);

}
发表评论