Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C & KeyValueCoding: How to avoid an exception with valueForKeyPath:?

I've got an object of type id and would like to know if it contains a value for a given keyPath:

[myObject valueForKeyPath:myKeyPath];

Now, I wrap it into a @try{ } @catch{} block to avoid exceptions when the given keypath isn't found. Is there a nicer way to do this? Check if the given keypath exists without handling exceptions?

Thanks a lot,

Stefan

like image 688
swalkner Avatar asked Dec 19 '11 12:12

swalkner


People also ask

What is Objective-C used for?

Objective-C is general-purpose language that is developed on top of C Programming language by adding features of Small Talk programming language making it an object-oriented language. It is primarily used in developing iOS and Mac OS X operating systems as well as its applications.

Is Objective-C or C++ harder?

In my opinion, probably the biggest difference is the syntax. You can achieve essentially the same things in either language, but in my opinion the C++ syntax is simpler while some of Objective-C's features make certain tasks (such as GUI design) easier thanks to dynamic dispatch.

Is Objective-C still used?

While Objective-C is still supported by Apple and will likely not be deprecated anytime soon, there will be no updates to the language.

Is Objective-C better than C?

Objective C can be called the super set of C language. It contains classes and objects in addition to C language. The pointers used in C language are vulnerable to security attacks. The language objective C uses null pointers and hence is type safe compared to C.


2 Answers

You could try this:

if ([myObject respondsToSelector:NSSelectorFromString(myKeyPath)])
{
}

However, that may not correspond to the getter you have, especially if it is a boolean value. If this doesn't work for you, let me know and I'll write you up something using reflection.

like image 80
Richard J. Ross III Avatar answered Oct 24 '22 07:10

Richard J. Ross III


For NSManagedObjects, an easy solution is to look at the object's entity description and see if there's an attribute with that key name. If there is, you can also take it to the next step and see what type of an attribute the value is.

Here's a simple method that given any NSManagedObject and any NSString as a key, will always return an NSString:

- (NSString *)valueOfItem:(NSManagedObject *)item asStringForKey:(NSString *)key {

    NSEntityDescription *entity = [item entity];
    NSDictionary *attributesByName = [entity attributesByName];
    NSAttributeDescription *attribute = attributesByName[key];

    if (!attribute) {
        return @"---No Such Attribute Key---";
    }
    else if ([attribute attributeType] == NSUndefinedAttributeType) {
        return @"---Undefined Attribute Type---";
    }
    else if ([attribute attributeType] == NSStringAttributeType) {
        // return NSStrings as they are
        return [item valueForKey:key];
    }
    else if ([attribute attributeType] < NSDateAttributeType) {
        // this will be all of the NSNumber types
        // return them as strings
        return [[item valueForKey:key] stringValue];
    }
        // add more "else if" cases as desired for other types

    else {
        return @"---Unacceptable Attribute Type---";
    }
}

If the key is invalid or the value can't be made into a string, the method returns an NSString error message (change those blocks to do whatever you want for those cases).

All of the NSNumber attribute types are returned as their stringValue representations. To handle other attribute types (e.g.: dates), simply add additional "else if" blocks. (see NSAttributeDescription Class Reference for more information).

like image 25
Elmer Cat Avatar answered Oct 24 '22 09:10

Elmer Cat