Substituting JSON null values in Mantle - ios

I'm using Mantle to parse some JSON which normally looks like this:
"fields": {
"foobar": 41
}
However sometimes the value of foobar is null:
"fields": {
"foobar": null
}
This causes MTLValidateAndSetValue to throw an exception as it's trying to set a nil value via Key-Value Coding.
What I would like to do is detect the presence of this null value and substitute it with -1.
I tried overriding foobarJSONTransformer in my MTLModel subclass as follows:
+ (NSValueTransformer *)foobarJSONTransformer {
return [MTLValueTransformer transformerWithBlock:^id(id inObj) {
if (inObj == [NSNull null]) {
return [NSNumber numberWithInteger: -1];
} else {
return inObj;
}
}];
...and I can see this code being called but inObj is never equal to [NSNull null], hence the substitution doesn't happen and the exception is still thrown by Mantle.
What is the correct way to catch this JSON null case and do the substitution?

I had incorrectly assumed NSNull would be generated for a null JSON value. In fact it is parsed to a nil value.
So the solution is to check inObj against nil, rather than NSNull:
+ (NSValueTransformer *)foobarJSONTransformer {
return [MTLValueTransformer transformerWithBlock:^id(id inObj) {
if (inObj == nil) {
return [NSNumber numberWithInteger: -1];
} else {
return inObj;
}
}];
the substitution will then work as expected.

If you received as null, it will generated as NSNull. But if they missed this field or send it as empty, it will generate as nil while parsing. so better you can use below code
if (inObj == nil || inObj == [NSNull null] )

create a base model and inherit MTLModel,and override blow code:
- (void)setNilValueForKey:(NSString *)key {
[self setValue:#0 forKey:key];
}
if you property is oc object,it will be nil immediate,and can't execute the method.but it can execute if the property is int,bool or float.

Related

swift: EXC_BAD_ACCESS with using Realm and FolioReaderKit

I installed FolioReaderKit using Cocoapods to read epub book. I'm trying to highlight text and add it to a list of highlights. But when I do this I get this error and my app crashes:
Thread 1: EXC_BAD_ACCESS (code=257, address=0x41c4a1c96ae55d46)
line:
value = RLMGetOptional(static_cast<RLMOptionalBase *>(object_getIvar(obj, prop.swiftIvar)));
in RLMAccessor.mm:
id RLMAccessorContext::propertyValue(__unsafe_unretained id const obj, size_t propIndex,
__unsafe_unretained RLMProperty *const prop) {
// Property value from an NSArray
if ([obj respondsToSelector:#selector(objectAtIndex:)]) {
return propIndex < [obj count] ? [obj objectAtIndex:propIndex] : nil;
}
// Property value from an NSDictionary
if ([obj respondsToSelector:#selector(objectForKey:)]) {
return [obj objectForKey:prop.name];
}
// Property value from an instance of this object type
id value;
if ([obj isKindOfClass:_info.rlmObjectSchema.objectClass] && prop.swiftIvar) {
if (prop.array) {
return static_cast<RLMListBase *>(object_getIvar(obj, prop.swiftIvar))._rlmArray;
}
else if (prop.swiftIvar == RLMDummySwiftIvar) {
// FIXME: An invalid property which we're pretending is nil until 4.0
// https://github.com/realm/realm-cocoa/issues/5784
return NSNull.null;
}
else { // optional
value = RLMGetOptional(static_cast<RLMOptionalBase *>(object_getIvar(obj, prop.swiftIvar)));
}
}
else {
// Property value from some object that's KVC-compatible
value = RLMValidatedValueForProperty(obj, [obj respondsToSelector:prop.getterSel] ? prop.getterName : prop.name,
_info.rlmObjectSchema.className);
}
return value ?: NSNull.null;
}
How to fix it?

Cannot access more than one value from function using PromiseKit Swift

TemplateClass.m
+ (AnyPromise *) promisefunctionReturnThreeValus:(NSString *)sampleName {
return [self anotherPromiseFunction:sampleName].then(^(NSMutableDictionary *sampleDict) {
DataArray *data = [DataArray dataArrayFromDict:sampleDict];
PropertyArray *property = [PropertyArray PropertyArrayFromDict:sampleDict];
if ([sampleDict objectForKey:NAME])
{
NameModel *name = [[NameModel alloc]initWithDictionary:[responseDict objectForKey:NAME]];
return (PMKManifold(data,property,name));
}
else
{
return (PMKManifold(data,property,nil));
}
});
}
well i can able to access this from objc using the below code
[TemplateClass promisefunctionReturnThreeValus:#"hello"].then(^(DataArray *data,PropertyArray *property,NameModel *name) {
//Here i can able to access the three values data,property and name
}
But when i try to access this from swift
TemplateClass.promisefunctionReturnThreeValus(sampleName: "hello").then{ data,property,name in
// it show me error " Contextual closure type '(Any?) -> AnyPromise' expects 1 argument, but 3 were used in closure body "
}
i can able to access only data but not the other two
i also tried debug it and print through log it show only the data of DataArray Object
lldb output
<DataArray : 0x1c0631340 count:1 value:{
"id" = 3631;
}
>

object return empty description in iOS

hello I am doing something like this.
NSString * fblink=[dm.commonDataArray valueForKey:#"fb_link"];
if(![fblink isEqual:[NSNull null]]||![fblink isEqualToString:#""]||![fblink length]<=0)
{
[fb_button setImage:[UIImage imageNamed:#"ico_user_fb"] forState:UIControlStateNormal];
[fb_button addTarget:self
action:#selector(buttonFBTouch:)
forControlEvents:UIControlEventTouchUpInside];
}else{
[fb_button setImage:[UIImage imageNamed:#"ico_fb_red_gray"] forState:UIControlStateNormal];
}
when I type fblink in my log it says (lldb) po fblink
<object returned empty description> But still my if condition become true and go inside ratherthan going to else part.
How can I overcome this problem?I dont want to execute my if condition true part if its return empty description. How can I checked this condition? Please help me
Thanks
The problem is with your if condition. fblink is nil, you are checking nil is equal to [NSNull null] so this case fails and you invert the result so it becomes true and goes inside of this if case.
If we expand your if case it becomes:
if(![nil isEqual:[NSNull null]]||![nil isEqualToString:#""]||![nil length]<=0)
{
}
Which becomes
if(!false||!false||!true) // which evaluates to true, you are using ||, so if any one condition is true, it will go inside of the if case
{
}
You need to change that if case to:
if([fblink isKindOfClass:[NSString class]] && ![fblink length]<=0)
{
}
else
{
}
you can try.....
if(![fblink isEqual:[NSNull null]]&&![fblink isEqualToString:#""]&&![fblink length]<=0)
{
//your code here .......
}
else
{//your code here ...}
I think that the fblink is not null but its an empty string. Thus your ![fblink isEqual:[NSNull null]] is becoming true and your if statement is getting executed. Only check it with the following condition:
if(![fblink isEqualToString:#""]||![fblink length]=0)
You have to change the || (or) condition to &&(and) condition.
Try this:
if(![fblink isEqual:[NSNull null]]&&![fblink isEqualToString:#""]&&![fblink length]<=0 )
{
//your code
}
else
{
// your code
}

How to check if an object is nil in Objective-C? [duplicate]

This question already has answers here:
Testing for nil in Objective-C -- if(x != nil) vs if(x)
(4 answers)
Closed 7 years ago.
So I know this seems pretty basic but it doesn't seem to be working for some reason. I have the following code.
Target *t = self.skill.target;
if (![t isEqual:nil]) {
NSLog(#"Not nil");
}
I tried this and it comes up as not nil everytime which is great except for when t should actually be nil. I even tried putting variation into the code like so and my t is still coming up as not nil for some reason. Am I doing something wrong? :\
Target *t = self.skill.target;
t = nil;
if (![t isEqual:nil]) {
NSLog(#"Not nil");
}
You can do it normally just by checking the object itself. There is also a good explanation on NSHipster for NSNull.
if( myObject ){
// do something if object isn't nil
} else {
// initialize object and do something
}
otherwise just use
if( myObject == nil ){
}
Target *t = self.skill.target;
t = nil;
if (t) {
NSLog(#"t is Not nil");
}
if (!t) {
NSLog(#"t is nil");
}
As this answer says:
Any message to nil will return a result which is the equivalent to 0 for the type requested. Since the 0 for a boolean is NO, that is the result.
So, a nil object is special. you can't compare it using the isEqual method. you should compare it without sending it a message, like this:
if (t)
{
}
or simply:
if (t != nil)
{
}
The if operation checks nillable so this should works:
Target *t = self.skill.target;
if (t) {
NSLog(#"Not nil");
}else{
NSLog(#"nil");
}
Hope it helps.

About NSArray nil crash error

How to avoid this crash error!Crash in main thread Log is
ProcessArray:()
ProcessArray == 0
-[NSNull length]: unrecognized selector sent to instance 0x3c4e1090
my code:
ProcessArray = [EventSheetDetailArray valueForKey:#"Process"];
NSLog(#"ProcessArray:%#",ProcessArray);
if (ProcessArray.count > 0 ) {
NSLog(#"ProcessArray != 0");
[self ProcessJSONDateFormat];
}else{
NSLog(#"ProcessArray == 0");
}
I change judge below!
id value = [EventSheetDetailArray valueForKey:#"Process"];
if ( ![[NSNull null] isEqual:value] )
{
ProcessArray = value;
NSLog(#"1111111");
}else{
NSLog(#"2222222");
}
But always run NSLog(#"1111111") this line!
Regardless of whether any value!
Validate the return value from [EventSheetDetailArray valueForKey:#"Process"]
id value = [EventSheetDetailArray valueForKey:#"Process"];
if ( ![[NSNull null] isEqual:value] )
{
ProcessArray = value;
}
OR
id value = [EventSheetDetailArray valueForKey:#"Process"];
if ( [value isKindOfClass:[NSArray class]] )
{
ProcessArray = value;
}
then you can call NSArray member functions, don't just assume it is NSArray..
The answer is actually quite simple.
if([ProcessArray count] != [NSNULL NULL]) {
if (ProcessArray.count > 0 ) {
NSLog(#"ProcessArray != 0");
[self ProcessJSONDateFormat];
}else {
NSLog(#"ProcessArray == 0");
}
}else {
NSLog(#"NULL...insert some value");
}
Sorry!I found the cause of the error,Because my other code have error, That caused crash main thread -[NSNull length] reason!
If your array is empty then you can't check for count otherwise it will crash.I faced the same issue.Just use "if(!(array==nil))".This is true when your array is empty otherwise it will move to else part.

Resources