Null Value causes Realm Crashed - ios

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.

Related

objective c [__NSArrayM objectForKey:]: unrecognized selector sent to instance

I declared DATA as below
#property (strong, nonatomic) NSDictionary *DATA;
My table in console DATA is :
(
{
comment = "";
deadline = deadline;
id = 2;
responsible = "responsable action 1";
status = pending;
title = "";
}
)
But problem in NSLog(#"%#",[DATA objectForKey:#"deadline"]);
You are using this DATA object as a NSDictionary but it is a NSArray. You can check your log which is start from ( which indicate it is a Array.
You can also check like this,
if ([DATA isKindOfClass:[NSDictionary class]]) {
//then this is dictionary
}else{
// other datatype
}
before use as NSLog(#"%#",[DATA objectForKey:#"deadline"]).
If you want to access for now you can use as, but for that this DATA should be as NSArray or NSMutableArray.
#property (strong, nonatomic) NSArray *DATA;
[[DATA objectAtIndex:0] objectForKey:#"deadline"]
The above JSON response is an Array and not a Dictionary, () = Array and {} = Dictionary.
Ideally, you should have something like,
{
"comment":"",
"deadline":"deadline",
"id":2,
"responsible":"responsable action 1",
"status":"pending",
"title":""
}
Still, you can try using an array instead of a dictionary and check if it gives you an error while parsing.

__NSDictionaryI setObject:forKey: Crash

The problem is that I am mutating a NSDictionary, but even after getting a mutableCopy, the app crashes.
Below is Method for copy :
+ (NSMutableDictionary *)updateQuery:(NSMutableDictionary *)currentQuery toSearchAfterAccountPaginationSequence:(NSString *)accountPaginationSequence {
//try1
NSMutableDictionary *mutableQuery = [currentQuery mutableCopy];
//try2
NSMutableDictionary *mutableQuery2=[NSMutableDictionary dictionaryWithDictionary:currentQuery];
//crashes on this line
mutableQuery[#"where"][#"account_pagination_sequence"] = #{ #"lt" : accountPaginationSequence };
return mutableQuery;
}
Error Log (the app crashes on a limited amount of devices)
[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance
i think this is what you trying to achieve
+ (NSMutableDictionary *)updateQuery:(NSMutableDictionary *)currentQuery toSearchAfterAccountPaginationSequence:(NSString *)accountPaginationSequence {
//try1
NSMutableDictionary *mutableQuery = currentQuery.mutableCopy;
NSMutableDictionary *where = mutableQuery[#"where"].mutableCopy;
where[#"account_pagination_sequence"] = #{ #"lt" : accountPaginationSequence };
mutableQuery[#"where"] = where;
return mutableQuery;
}
Edit:
In Objective-C calling mutableCopy on objects is not recursive.You need to call mutableCopy in nested objects too.

NSInvalidArgumentException', reason: '-[__NSArrayI length]: unrecognized selector sent to instance 0x165d5150'

Hi I am getting this data form server
NSDictionary*feed=[saveDic objectForKey:#"feed"];
NSLog(#"%#",feed); //Outputs: feed = ( { code = yQ7j0t; "user_id" = 889445341091863; } ); }
NSLog(#"%#",[feed valueForKey:#"code"]);
NSString *referralCode = [feed valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=referralCode;
And beacuse of that I am getting below error.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: selector sent to instance 0x165d5150'``
Any help will be appreciated.
The issue is, your feed key holds an array. You are not properly handling that in your code, that is why the crash occurs. When you call valueForKey: it retrieves an array of values held by that specific key.
For fixing that you can use:
NSArray *feed = [saveDic objectForKey:#"feed"];
NSArray *referralCodes = [feed valueForKey:#"code"];
NSString *referralCode = referralCodes.count ? referralCodes[0] : #"";
NSLog(#"%#",referralCode);
But I personally prefer using objectForKey: instead of valueForKey:. So you can re-write the code like:
NSArray *feed = [saveDic objectForKey:#"feed"];
NSString *referralCode = feed.count ? [feed[0] objectForKey:#"code"] : #"";
NSLog(#"%#",referralCode);
Some where you use a variable;
yourVaribleName.length
or
[yourVaribleName length]
which should be
yourVaribleName.count
note: the crash says exactly that "yourVaribleName" is NSArray type where you wants length of the NSArray. But NSArray has not feature "length". NSArray has "Count" feature
//try with this code bellow
NSArray *referralCode = [feed valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=[referralCode componentsJoinedByString:#" "];//#"," or #"" what event you need
Your feed data is in array. So you have retrieve code value from array.Hope it will help you.
NSMutableArray*feed=[saveDic objectForKey:#"feed"];
NSLog(#"%#",feed);
NSLog(#"%#",[feed valueForKey:#"code"]);
NSString *referralCode = [[feed objectAtIndex:indexPath]valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=referralCode;

Message sent to deallocated instance with ARC using custom getter and setter

I'm trying to implement a custom getter and setter for my custom object HFObject and my app crashed with a Message sent to deallocated instance error despite using ARC.
I've read every single related post, the ones that were written pre-ARC don't apply, and everything else didn't help. I have the zombie object debugger option turned on.
Setting up the custom HObject
Within HObject.h I have declared these four properties:
#property (retain) NSString *email; //Will use custom getter/setter
#property (retain) NSString *firstName; //Will use custom getter/setter
#property (retain) NSDate *date; //Will use custom getter/setter
#property (nonatomic, retain) NSMutableDictionary *values;
In the implementation of HObject, I have removed the automatic getting and setting of email. firstName, and date by utilizing #dynamic like so
#dynamic email;
#dynamic firstName;
#dynamic date;
I also allocate the values dictionary in my HObject init
- (id)init {
self = [super init];
if (self) {
self.values = [NSMutableDictionary dictionary];
}
return self;
}
Implementing Custom Getter & Sender
For my custom getter/setter. I have overridden
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
and
- (void)forwardInvocation:(NSInvocation *)invocation
As shown below:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSString *sel = NSStringFromSelector(selector);
if ([sel rangeOfString:#"set"].location == 0) {
return [NSMethodSignature signatureWithObjCTypes:"v#:#"];
} else {
return [NSMethodSignature signatureWithObjCTypes:"##:"];
}
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
NSString *key = NSStringFromSelector([invocation selector]);
if ([key rangeOfString:#"set"].location == 0) {
key = [key substringWithRange:NSMakeRange(3, [key length]-4)];
id obj;
[invocation getArgument:&obj atIndex:2];
[self.values setObject:obj forKey:key];
} else {
id obj = [self.values objectForKey:key];
[invocation setReturnValue:&obj];
}
}
What I'm trying to do here is store all of the values of the property into my values dictionary and retrieve them from there as well.
App Crashing
In the implementation of my view controller, I try to create a HObject and set values for my properties, and then I log the values dictionary to see all of my values.
- (void)buttonPressed:(id)sender {
HObject *obj = [[HObject alloc] init];
NSString *name = #"this is a string object";
obj.date = [NSDate date];
obj.email = #"email#website.com";
obj.firstName = [NSString stringWithFormat:#"%#", name];
NSLog(#"Values %#", [obj values]);
}
At that point the app crashes and this is my console log
2014-07-27 04:12:37.899 App[61501:60b] Values {
Date = "2014-07-27 08:12:37 +0000";
Email = "email#website.com";
FirstName = "this is a string object";
}
2014-07-27 04:12:37.901 HeadsUp[61501:60b] *** -[CFString release]: message sent to deallocated instance 0x109473fe0
If you can help me from here, I would greatly appreciate it. I am also including my debugging process in case that will help you
My debugging Process (Long, skip if you can already help me)
I originally created many of these objects and stored them in an array, and when I do that, as opposed to creating a single object. my app crashed a bit different.
My array:
#property (nonatomic, strong) NSArray *array;
Methods:
- (void)createArray
{
int i = 1; //number of testobjs
NSMutableArray *objects = [NSMutableArray arrayWithCapacity:i];
for (int j = 0; j<i; j++) {
HFObject *obj = [[User alloc] init];
NSString *name = #"this is a string object";
[obj setObject:[NSDate date] forKey:#"Date"];
obj.email = #"email#website.com";
obj.firstName = [NSString stringWithFormat:#"%#", name];
[objects addObject:obj];
}
self.array = [NSArray arrayWithArray:objects];
}
- (void)buttonPressed:(id)sender {
HObject *object = [self.array objectAtIndex:0];
NSLog(#"Values %#", [object values]);
}
Crash log:
2014-07-27 04:34:02.893 App[61623:60b] *** -[CFString isNSString__]: message sent to deallocated instance 0x1094988f0
(lldb)
Now this crash log is almost the same as the one before, except this didn't log the values inside of [object values]
Investigating the issue a bit, I looked at the left window (not sure what it is actually called) of the debugger and I saw this:
(Treat HFObject as HObject and dirtyValues as values; I renamed them for presentational purposes)
You can see that under the key #"FirstName" there is no value.
I did several similar tests where I changed the values of the properties I was setting and changed the data types. More often than not, not only did FirstName not have a value, neither did Date. However, the value of email was always present.
After researching about dataTypes, I realized it was because email was a string literal which can't deallocated. On the other hand firstName and date were objects, which can be deallocated.
The crash log refers to a CFString property, which I learned doesn't use ARC. I never created a Core Foundation object, so I set out to found out it was being created in setter by logging the [obj class]:
- (void)forwardInvocation:(NSInvocation *)invocation
{
NSString *key = NSStringFromSelector([invocation selector]);
if ([key rangeOfString:#"set"].location == 0) {
key = [key substringWithRange:NSMakeRange(3, [key length]-4)];
id obj;
[invocation getArgument:&obj atIndex:2];
NSLog(#"%#", [obj class]); //I ADDED THIS LOG
[self.values setObject:obj forKey:key];
} else {
id obj = [self.values objectForKey:key];
[invocation setReturnValue:&obj];
}
}
After crashing one more time, I got the obj classes
2014-07-27 04:58:03.893 HeadsUp[61765:60b] __NSDate
2014-07-27 04:58:03.894 HeadsUp[61765:60b] __NSCFConstantString
2014-07-27 04:58:03.894 HeadsUp[61765:60b] __NSCFString
2014-07-27 04:58:03.904 HeadsUp[61765:60b] *** -[__NSDate release]: message sent to deallocated instance 0x109554370
(lldb)
Here you can see Date is being deallocated for some reason, and my string are now __NSCF strings.
I tried resetting the strings to NSStrings using (__brigde NSString *)obj and every other possible way you can bridge a CF object to ARC, however that didn't work either.
Here is everything I've done. I appreciate any and all help.
The problem is here:
id obj;
[invocation getArgument:&obj atIndex:2];
getArgument simply copies the object pointer into obj without retaining it.
However, since obj is (by default) a __strong variable, it will be released at
the end of the current method. To solve the problem, use
__unsafe_unretained id obj;
[invocation getArgument:&obj atIndex:2];
Note also that your getter implementation does not work. For example, setFirstName:
stores the key in the dictionary using the key "FirstName", but the getter firstName
tries to read the value for the key "firstName".
(As already mentioned in a comment, it would probably easier and less error-prone
to just override the accessor methods for the three properties separately, instead
of dynamic forwarding.)

Why do i get an error comparing NSString's? (-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance)

I have a NSMutableArray (_theListOfAllQuestions) that I am populating with numbers from a file. Then I compared the objects in that array with qNr (NSString) and I got error. I even casted the array to another NSString, _checkQuestions, just to be sure I am comparing NSStrings. I tested using item to compare also.
-(void)read_A_Question:(NSString *)qNr {
NSLog(#"read_A_Question: %#", qNr);
int counter = 0;
for (NSString *item in _theListOfAllQuestions) {
NSLog(#"item: %#", item);
_checkQuestions = _theListOfAllQuestions[counter]; //_checkQuestion = NSString
NSLog(#"_checkQuestions: %#", _checkQuestions);
if ([_checkQuestions isEqualToString:qNr]) {
NSLog(#">>HIT<<");
exit(0); //Just for the testing
}
counter++;
}
When running this code i get the following NSLog:
read_A_Question: 421
item: 1193
_checkQuestions: 1193
...and error:
-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x9246d80
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber
isEqualToString:]: unrecognized selector sent to instance 0x9246d80'
I do believe that I still comparing NSString with a number of some sort but to me it looks like I am comparing NSString vs. NSString?
I could really need some help here to 1) understand the problem, 2)solve the problem?
Replace this line
if ([_checkQuestions isEqualToString:qNr])
with
if ([[NSString stringWithFormat:#"%#",_checkQuestions] isEqualToString:[NSString stringWithFormat:#"%#",qNr]])
Hope it helps you..
Your _theListOfAllQuestions array has NSNumber objects and not NSString objects. So you cant use isEqualToString directly.
Try this,
for (NSString *item in _theListOfAllQuestions) {
NSLog(#"item: %#", item);
_checkQuestions = _theListOfAllQuestions[counter]; //_checkQuestion = NSString
NSLog(#"_checkQuestions: %#", _checkQuestions);
if ([[_checkQuestions stringValue] isEqualToString:qNr]) {
NSLog(#">>HIT<<");
exit(0); //Just for the testing
}
counter++;
}

Resources