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

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.

Related

What is the Objective C equivalent of self.view.traitCollection.horizontalSizeClass?

What is the obj c code for below swift statement?
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact)
what i figured out so far is proviede below but it is giving error when i add self.view
if ([self.view UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact])
{
NSLog(#"Compact");
}
Try this
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
// do your stuff
}
Hope it works

iOS: Check if boolean is nil (Objective-C)

I'm checking in the console if child viewcontroller is loaded:
po self.childVC.isViewLoaded
<nil>
My question to you guys is how can check if boolean is nil ?
What about checking like this?
If assume that boolean can be nil then..
// Can check nil & NO for isViewLoaded
if (self.childVC.isViewLoaded != NO) {
//blah
}
Already asked. Please check this How to check if a BOOL is null?
if (self.childVC.isViewLoaded != [NSNull null]) {
}
else {
}
Thanks
LLDB: As simple as p self.childVC.isViewLoaded
CODE: if (self.childVC.isViewLoaded) {//isViewLoaded = YES}
A BOOL is either YES or NO. There is no other state.
To check if the view is loaded add below code,
if (self.childVC.isViewLoaded && self.childVC.view.window) {
// self.childVC is visible
}

MPTweakValue without internet

I try to implement Mixpanel's tweaks into my app for A/B testing. This is my code:
if (MPTweakValue(kFeaturedOffersTweak, NO)) {
return MenuItemRowHeight;
}
else {
return 0;
}
On the first lunch everything is OK and tweak value is YES. Then I switch off internet on my iPhone, open run again and tweak value is NO.
What is correct way to use Mixpanel's tweak without internet?
So, I created my custom manager, where I implemented tweaks' persistency.
Please, let me know, if you have better solution.
My code:
-(void)initManager {
[[Mixpanel sharedInstance] joinExperimentsWithCallback:^{
USE_SETTINGS;
SETTINGS_SETBOOL(kPreferredPartnersTweak, MPTweakValue(kPreferredPartnersTweak, NO));
SYNCHRONIZE_SETTINGS;
//===
SEND_NOTIF(kTweaksUpdated, nil);
}];
}
-(BOOL)getTweakWithName:(NSString*)tweakName {
BOOL result = NO;
//===
USE_SETTINGS;
if (SETTINGS_BOOL(tweakName)) {
result = SETTINGS_BOOL(tweakName);
}
else {
result = MPTweakValue(kPreferredPartnersTweak, NO);
}
//===
return result;
}
USE_SETTINGS, SETTINGS_BOOL, SYNCHRONIZE_SETTINGS is my macros wrappers for working with NSUserDefaults.

Substituting JSON null values in Mantle

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.

If statement not calling all methods returning BOOL

I have code like this:
-(IBAction)send {
if ([self isCorrect1] && [self isCorrect2] && ...) {
[self sendRequest];
}
}
-(BOOL)isCorrect1 {
...
}
-(BOOL)isCorrect2 {
...
}
Every isCorrect method is checking some condition showing some message in the view and returning result of the checking. I noticed that if first condition is false it will only show error message for the first method (and I need all of them to be checked) and no breakpoint is triggered inside these methods. I thought it was some kind of LLVM optimization so I created code like this:
-(IBAction)send {
BOOL correct = [self isCorrect1];
correct = correct && [self isCorrect2];
...
if (correct) {
[self sendRequest];
}
}
And is still not working correctly. Do I have to create new BOOL variable to store result for the check or is there some other way?
Since the first condition is evaluated to false, it won't check for the rest of the conditions and will go to the else part straightaway.
Try this.
BOOL finalResult = [self isCorrect1];
finalResult = [self isCorrect2] && finalResult;
finalResult = [self isCorrect3] && finalResult;
finalResult = [self isCorrect4] && finalResult;
...
if (finalResult) {
}
This will go through all of the isCorrect tests and will let you know if it passed all of them in the end or not.
The behaviour you see is the expected behaviour of the &&, namely, it "short-circuits" the evaluation, if it can determine the result in advance, before having evaluated all conditions:
expression-yielding-false && something-else
The result of the above is completely determined by the first part; regardless of what the second operand yields, the final result is false. This allows you to write something like:
if (obj != null && obj->count == 3)
{
...
}
If the && did not have the short-circuit behaviour, you'd have to write
if (obj != null)
{
if (obj->count == 3)
{
...
}
}
The || has a similar behaviour. In case of
something-yielding-true || anything
the right-hand side cannot affect the result value, as the left-hand side already returned true.
One possible work-around would be:
int succeeses = 0;
succeesses += [self isCorrect1]? 1 : 0;
succeesses += [self isCorrect2]? 1 : 0;
succeesses += [self isCorrect3]? 1 : 0;
if (successes == 3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
If you need to know, which tests passed, and which failed, you can try:
BOOL passed1 = [self isCorrect1];
BOOL passed2 = [self isCorrect2];
BOOL passed3 = [self isCorrect3];
if (passed1 && passed2 && passed3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
A more dense version of the above would be
int passed = 0;
passed |= [self isCorrect1]? (1 << 0) : 0;
passed |= [self isCorrect2]? (1 << 1) : 0;
passed |= [self isCorrect3]? (1 << 2) : 0;
if (passed == 7)
{
// All tests did succeed
}
else
{
if (passed & (1 << 0))
{
// First test passed
}
else
{
// First test failed
}
if (passed & (1 << 1))
{
// Second test passed
}
else
{
// Second test failed
}
if (passed & (1 << 2))
{
// Third test passed
}
else
{
// Third test failed
}
}
which is simply a more occult formulation of the version with a boolean variable per test tried.

Resources