I'm developing an iOS 5.0+ app with latest SDK.
I get a very strange error with this code:
- (NSMutableURLRequest*)setupRequestWithService:(NSString*)service andMethod:(NSString*)method
{
NSString* url = [NSString stringWithFormat:#"%#%#.svc/%#", serverUrl, service, method];
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
// Set authentication token.
NSLog(#"???????????? %#", authenticationToken);
if (authenticationToken == nil)
NSLog(#"NULL AUTHTOKEN");
if ([authenticationToken isEqual:[NSNull null]])
NSLog(#"NSNULL AUTHTOKEN");
if (request == nil)
NSLog(#"NULL REQUEST");
[request addValue:authenticationToken forHTTPHeaderField:REQUEST_HEADER_AUTH_TOKEN];
return request;
}
This is my log:
???????????? <null>
NSNULL AUTHTOKEN
-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090'
It seems that authenticationToken is NULL. But I don't understand that, if authenticationToken is NULL why I don't see NULL AUTHTOKEN on the log.
I get this error the second time I run that method, the first time, I don't get any error. This is my log:
???????????? (null)
NULL AUTHTOKEN
By the way:
NSString* authenticationToken;
Any advice?
Maybe there is a Memory Leak somewhere...
My solution to this maddening use of NSNull by JSON interpreters is to create a category on NSNull, where I define integerValue, floatValue, length, etc - return 0 for all. Everytime you get another crash add a new category. I think I had 6 or 7 when I had this issue.
The problem with NOT doing this is you have to look for the NULL everywhere in your converted objects - a PITA in my opinion.
EDIT: the code I'm using, all in a NSNull+JSON.m file:
#interface NSNull (JSON)
#end
#implementation NSNull (JSON)
- (NSUInteger)length { return 0; }
- (NSInteger)integerValue { return 0; };
- (float)floatValue { return 0; };
- (NSString *)description { return #"0(NSNull)"; }
- (NSArray *)componentsSeparatedByString:(NSString *)separator { return #[]; }
- (id)objectForKey:(id)key { return nil; }
- (BOOL)boolValue { return NO; }
#end
EDIT2: Now in Swift 3:
extension NSNull {
func length() -> Int { return 0 }
func integerValue() -> Int { return 0 }
func floatValue() -> Float { return 0 };
open override var description: String { return "0(NSNull)" }
func componentsSeparatedByString(separator: String) -> [AnyObject] { return [AnyObject]() }
func objectForKey(key: AnyObject) -> AnyObject? { return nil }
func boolValue() -> Bool { return false }
}
The error message is pretty clear. NSNull and nil are different things:
The NSNull class defines a singleton object used to represent null values in
collection objects (which don’t allow nil values).
If you want to check if authenticationToken is NSNull try: [authenticationToken isEqual: [NSNull null]]
In line with David H's answer, how about a category on NSNull that just uses ObjC's message forwarding to "do nothing", to emulate the runtime's behavior when sending messages to nil?
Like this:
#interface NSNull (ForwardInvocation)
#end
#implementation NSNull (ForwardInvocation)
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [NSNull methodSignatureForSelector:#selector(description)];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
// do nothing; prevent 'unrecognized selector' crashes
}
#end
The [NSNull methodSignatureForSelector:#selector(description)]; takes advantage of the fact that NSNull inherits from NSObject, which provides the description method. This satisfies the forwarding mechanism requirement for implementing -methodSignatureForSelector:.
The problem comes because your method return an NSNull object.
You can't check [authenticationToken isEqual:[NSNull null]]) because [NSNull null] give an instance of an object. So it's different from your object itself.
If you want to check if you received an NSNull object you need to check like this: [authenticationToken isKindOfClass:[NSNull class]] instead.
Related
I'm getting Json response with subArrays of dictionaries and I'm looking for particular value inside of one the subArrays. This is the subArray I care about:
<__NSArrayM 0x600000047680>(
{
value = "VeryImportanValue";
},
{
value = "someValue";
},
{
value = 0912131235235234;
}
)
I'm looking for the dictionary with the value of "VeryImportanValue". But as you can see you of the values are numeric and I check:
if ([[dict objectForKey:#"value"]isEqualToString:#"VeryImportanValue"])
I get this error:
-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance
But switch the if statement to fix the error above:
if ([[[dict objectForKey:#"value"] stringValue] isEqualToString:#"VeryImportanValue"])
I get this error:
-[__NSCFString stringValue]: unrecognized selector sent to instance
How can I check the value of the dictionary without getting any of this errors regarless if is string or numeric value?
I'll really appreciate your help.
You could create a method that turns the unknown object into a string:
- (NSString *)stringForStringOrNumber:(id)object
{
NSString *result = nil;
if ([object isKindOfClass:[NSString class]]) {
result = object;
} else if ([object isKindOfClass:[NSNumber class]]) {
result = [object stringValue];
} else {
result = #"I can't guess";
}
return result;
}
Before you do isEqualToString, you should first check the value type of your dictionary.
if(dict[#"value"]isKindOfClass==[NSString class]) //value is string
I am using Realm 0.92.3 but it crashed when I have null value despite I have set the default properties. Is there any solution on this? If not I might convert using coredata as this is very important to me. The null will be random on several properties
#interface WatchlistNews : RLMObject
#property NSString *nid;
#property NSString *tid;
#property NSString *country;
#end
#implementation WatchlistNews
+ (NSString *)primaryKey {
return #"nid";
}
+ (NSDictionary *)defaultPropertyValues {
return #{#"nid" : #"", #"tid": #"", #"country": #""};
}
#end
Data response:
nid = 509319;
tid = <null>;
country = my;
Error code:
-[NSNull UTF8String]: unrecognized selector sent to instance 0x10712b4c0
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull UTF8String]: unrecognized selector sent to instance 0x10712b4c0'
Realm do not support complex data types, so if you try to assign a complex value such as <null>, it gets crashed.
You should check the response you are getting from the server for the <null> values. And if it exists in the response replace it with an empty string. Try following code on the response you are getting, to remove the occurance of <null> values.
-(NSMutableDictionary *) removeNullFromDictionary:(NSDictionary *) originalDictionary{
NSArray *allKeysArray = [originalDictionary allKeys];
const NSMutableDictionary *replaced = [originalDictionary mutableCopy];
const id nul = [NSNull null];
const NSString *blank = #"";
for(NSString *key in allKeysArray) {
const id object = [originalDictionary objectForKey:key];
if(object == nul) {
[replaced setObject:blank forKey:key];
}
}
return [replaced copy];
}
Realm does not yet support setting nil for NSString properties, but you can track progress on that by following https://github.com/realm/realm-cocoa/issues/628.
I'm developing an iOS 5.0+ app with latest SDK.
I get a very strange error with this code:
- (NSMutableURLRequest*)setupRequestWithService:(NSString*)service andMethod:(NSString*)method
{
NSString* url = [NSString stringWithFormat:#"%#%#.svc/%#", serverUrl, service, method];
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
// Set authentication token.
NSLog(#"???????????? %#", authenticationToken);
if (authenticationToken == nil)
NSLog(#"NULL AUTHTOKEN");
if ([authenticationToken isEqual:[NSNull null]])
NSLog(#"NSNULL AUTHTOKEN");
if (request == nil)
NSLog(#"NULL REQUEST");
[request addValue:authenticationToken forHTTPHeaderField:REQUEST_HEADER_AUTH_TOKEN];
return request;
}
This is my log:
???????????? <null>
NSNULL AUTHTOKEN
-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090'
It seems that authenticationToken is NULL. But I don't understand that, if authenticationToken is NULL why I don't see NULL AUTHTOKEN on the log.
I get this error the second time I run that method, the first time, I don't get any error. This is my log:
???????????? (null)
NULL AUTHTOKEN
By the way:
NSString* authenticationToken;
Any advice?
Maybe there is a Memory Leak somewhere...
My solution to this maddening use of NSNull by JSON interpreters is to create a category on NSNull, where I define integerValue, floatValue, length, etc - return 0 for all. Everytime you get another crash add a new category. I think I had 6 or 7 when I had this issue.
The problem with NOT doing this is you have to look for the NULL everywhere in your converted objects - a PITA in my opinion.
EDIT: the code I'm using, all in a NSNull+JSON.m file:
#interface NSNull (JSON)
#end
#implementation NSNull (JSON)
- (NSUInteger)length { return 0; }
- (NSInteger)integerValue { return 0; };
- (float)floatValue { return 0; };
- (NSString *)description { return #"0(NSNull)"; }
- (NSArray *)componentsSeparatedByString:(NSString *)separator { return #[]; }
- (id)objectForKey:(id)key { return nil; }
- (BOOL)boolValue { return NO; }
#end
EDIT2: Now in Swift 3:
extension NSNull {
func length() -> Int { return 0 }
func integerValue() -> Int { return 0 }
func floatValue() -> Float { return 0 };
open override var description: String { return "0(NSNull)" }
func componentsSeparatedByString(separator: String) -> [AnyObject] { return [AnyObject]() }
func objectForKey(key: AnyObject) -> AnyObject? { return nil }
func boolValue() -> Bool { return false }
}
The error message is pretty clear. NSNull and nil are different things:
The NSNull class defines a singleton object used to represent null values in
collection objects (which don’t allow nil values).
If you want to check if authenticationToken is NSNull try: [authenticationToken isEqual: [NSNull null]]
In line with David H's answer, how about a category on NSNull that just uses ObjC's message forwarding to "do nothing", to emulate the runtime's behavior when sending messages to nil?
Like this:
#interface NSNull (ForwardInvocation)
#end
#implementation NSNull (ForwardInvocation)
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [NSNull methodSignatureForSelector:#selector(description)];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
// do nothing; prevent 'unrecognized selector' crashes
}
#end
The [NSNull methodSignatureForSelector:#selector(description)]; takes advantage of the fact that NSNull inherits from NSObject, which provides the description method. This satisfies the forwarding mechanism requirement for implementing -methodSignatureForSelector:.
The problem comes because your method return an NSNull object.
You can't check [authenticationToken isEqual:[NSNull null]]) because [NSNull null] give an instance of an object. So it's different from your object itself.
If you want to check if you received an NSNull object you need to check like this: [authenticationToken isKindOfClass:[NSNull class]] instead.
Trying to check for validity of the data in item
(item is NSDictionary)
I thought this should work but I do get into the second if and crash with:
unrecognized selector sent to instance
becuase galleryArr is (null)
NSArray *galleryArr = [item objectForKey:#"photos"];
if (galleryArr != nil ) {
if ([galleryArr count] != 0) {
//do something
}
}
Any ideas?
I've solved this issue with a simple this simple Objective-C category:
NSDictionary+NotNull.h
#import <Foundation/Foundation.h>
/*! This category extends NSDictionary to work around an issue with NSNull object.
*/
#interface NSDictionary (NotNull)
/*! #abstract Returns the value associated with a given key, but only if the value is not NSNull.
#param aKey The key for which to return the corresponding value.
#return The value associated with the given key, or nil if no value is associated with the key, or the value is NSNull.
*/
- (id)objectOrNilForKey:(id)aKey;
#end
NSDictionary+NotNull.m
#import "NSDictionary+NotNull.h"
#implementation NSDictionary (NotNull)
- (id)objectOrNilForKey:(id)aKey
{
id object = [self objectForKey:aKey];
if (object == [NSNull null]) {
return nil;
}
return object;
}
#end
Now you can just call:
NSArray *galleryArr = [item objectOrNilForKey:#"photos"];
Add a check for [gallryArr isKindOfClass:[NSArray class]].
Maybe you get NSNull? That's a singleton ([NSNull null]) object that represent nil. You can check if([gallryArr isKindOfClass:[NSArray class]]).
I'm developing an iOS 5.0+ app with latest SDK.
I get a very strange error with this code:
- (NSMutableURLRequest*)setupRequestWithService:(NSString*)service andMethod:(NSString*)method
{
NSString* url = [NSString stringWithFormat:#"%#%#.svc/%#", serverUrl, service, method];
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
// Set authentication token.
NSLog(#"???????????? %#", authenticationToken);
if (authenticationToken == nil)
NSLog(#"NULL AUTHTOKEN");
if ([authenticationToken isEqual:[NSNull null]])
NSLog(#"NSNULL AUTHTOKEN");
if (request == nil)
NSLog(#"NULL REQUEST");
[request addValue:authenticationToken forHTTPHeaderField:REQUEST_HEADER_AUTH_TOKEN];
return request;
}
This is my log:
???????????? <null>
NSNULL AUTHTOKEN
-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090'
It seems that authenticationToken is NULL. But I don't understand that, if authenticationToken is NULL why I don't see NULL AUTHTOKEN on the log.
I get this error the second time I run that method, the first time, I don't get any error. This is my log:
???????????? (null)
NULL AUTHTOKEN
By the way:
NSString* authenticationToken;
Any advice?
Maybe there is a Memory Leak somewhere...
My solution to this maddening use of NSNull by JSON interpreters is to create a category on NSNull, where I define integerValue, floatValue, length, etc - return 0 for all. Everytime you get another crash add a new category. I think I had 6 or 7 when I had this issue.
The problem with NOT doing this is you have to look for the NULL everywhere in your converted objects - a PITA in my opinion.
EDIT: the code I'm using, all in a NSNull+JSON.m file:
#interface NSNull (JSON)
#end
#implementation NSNull (JSON)
- (NSUInteger)length { return 0; }
- (NSInteger)integerValue { return 0; };
- (float)floatValue { return 0; };
- (NSString *)description { return #"0(NSNull)"; }
- (NSArray *)componentsSeparatedByString:(NSString *)separator { return #[]; }
- (id)objectForKey:(id)key { return nil; }
- (BOOL)boolValue { return NO; }
#end
EDIT2: Now in Swift 3:
extension NSNull {
func length() -> Int { return 0 }
func integerValue() -> Int { return 0 }
func floatValue() -> Float { return 0 };
open override var description: String { return "0(NSNull)" }
func componentsSeparatedByString(separator: String) -> [AnyObject] { return [AnyObject]() }
func objectForKey(key: AnyObject) -> AnyObject? { return nil }
func boolValue() -> Bool { return false }
}
The error message is pretty clear. NSNull and nil are different things:
The NSNull class defines a singleton object used to represent null values in
collection objects (which don’t allow nil values).
If you want to check if authenticationToken is NSNull try: [authenticationToken isEqual: [NSNull null]]
In line with David H's answer, how about a category on NSNull that just uses ObjC's message forwarding to "do nothing", to emulate the runtime's behavior when sending messages to nil?
Like this:
#interface NSNull (ForwardInvocation)
#end
#implementation NSNull (ForwardInvocation)
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [NSNull methodSignatureForSelector:#selector(description)];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
// do nothing; prevent 'unrecognized selector' crashes
}
#end
The [NSNull methodSignatureForSelector:#selector(description)]; takes advantage of the fact that NSNull inherits from NSObject, which provides the description method. This satisfies the forwarding mechanism requirement for implementing -methodSignatureForSelector:.
The problem comes because your method return an NSNull object.
You can't check [authenticationToken isEqual:[NSNull null]]) because [NSNull null] give an instance of an object. So it's different from your object itself.
If you want to check if you received an NSNull object you need to check like this: [authenticationToken isKindOfClass:[NSNull class]] instead.