Method parameter that can take an object or a nil? - objective-c

How do I spell a method whose argument can either be an object of a certain type, or nil? You see those all the time in framework classes, but I've just encountered my first instance where it would be useful to create one.

You can always pass nil instead of an object, there's nothing special you need to specify.

- (void) myMethod:(Parameter *)aParameter {
if (aParameter == nil) {
...
} else {
...
}
}
Elsewhere:
[anObject myMethod:foo];
Or:
[anObject myMethod:nil];

Related

Check object if it's equal to nil or to [NSNull null]

if object set to nil and I want to check for its value.
if object != nil {
// do something
}
or
if object != [NSNull null] {
// do something
}
I guess the second condition will be triggered but I am not sure why.
Can someone explain please?
As others have pointed out, object != nil && object != NSNull.null would give you the expected behaviour, however it might be tedious and error prone to write this pair of conditions every time.
Alternatively you can use inverted logic, by adding an nonNullValue method to virtually almost all objects in the system:
// in some header file
#interface NSObject(NullExtension)
- (instancetype)nonNullValue;
#end
// in some implementation file
#implementation NSObject(NullExtension)
// regular objects are not null (right?)
- (instancetype)nonNullValue {
return self;
}
#end
#implementation NSNull(NullExtension)
// let's make NSNull report as being null
- (instancetype)nonNullValue {
return nil;
}
#end
// adding this just for the sake of completeness, it's highly unlikely
// that JSON's will decode NSProxy instances
#implementation NSProxy(NullExtension)
- (instancetype)nonNullValue {
return self;
}
#end
you can then simply use it on your pointers:
// since we're in Objective-C, a nil pointer will always fail the check
// and thanks to the NSNull extension, NSNull instances will behave the same
if ([object nonNullValue] != nil) {
// NSNull won't get here
// nils won't get here
// other objects will get here
}
This approach is a little bit invasive as it touches all NSObject subclasses, however it eliminates the need of writing multiple conditions.
If you want to make sure object isn't nil and it isn't NSNull null then do:
if (object && object != [NSNull null]) {
// do something with object
} // else it's either nil or NSNull null
The difference between [NSNull null] and nil is that nil is an empty object that has completely disappeared from memory, and we use [NSNull null] when we want to express the idea that "we need a container that has nothing in it," which is "an object whose value is null." If you look up the development documentation you'll see that the class NSNull inherits NSObject and has only one "+ (NSNull *) null;" Class methods. This means that the NSNull object has a valid memory address, so any reference to it in the program will not cause the program to crash.

Are there Optional variables in Objective C?

I enjoy using the new Optional class in Java. Is there an equivalent in Objective C?
I need something that can hold a small value like nil until I try to get its value, at which point it is initialized and has the new value cached for next time I read it. I don't want to check if the object is nil at every point where I try to read its value.
You can lazy load the variable using a getter.
- (MyClass *) something {
if(!_something) {
_something = [MyClass new];
}
return _something;
}
Thus, each time you use instance.something, it will do the checking for you and load the object if it's not there already.
If it's a simple one-liner and you simply don't want to use if, you can skip out the keyword (I hear this is quicker, but can't verify that now):
- (MyClass *) something {
return _something ?: (_something = [MyClass new]);
}
This is very similar to the unwrapping in Swift where myObject?.aValue will return aValue only if myObject != nil. Or the if let statement: if let value = myObject?.aValue
In objective C, there is no specific syntax dedicated to this however you can easily test for existence using simple if statement e.g.: if(myObject). Because Objective-C objects are pointers and the address of a NULL pointer is 0x0 this if statement will evaluate to false if myObject is NULL (or nil if you like).
If you try to read a property of a nil object you will likewise get nil (for properties that are also objects). And if you try to set a nil object's property, nothing will happen.
I like to use the ternery operator as much as possible e.g.:string != nil ? [textField setText:string] : NULL;
As suggested in previous answers you can use lazy instantiation in your specific situation.

Passing nil object pointer in Objective-C

I create an object which I set to nil by default before including it in a method as a parameter. I do a check later if the object is still nil or not. The object is set to change in the method but the result is still nil. I'd expect the method to be able to alter the nil object. If I have the code that's inside the method replace the method call, it results in it being NOT nil.
MyObject *objectTemp = nil;
[self methodCallWithObject:objectTemp];
if (objectTemp == nil) NSLog(#"nil");
else NSLog(#"NOT nil");
// always results in "nil"
method:
-(void) methodCallWithObject:(MyObject)objectTemp {
objectTemp = [NSValue valueWithCGPoint:CGPointMake(5.3f, 2.6f)];
}
In order to change objectTemp outside of the method, you have to pass a pointer to objectTemp, which means that methodCallWithObject actually needs to take a pointer to a pointer:
-(void) methodCallWithObject:(MyObject **)objectTemp {
*objectTemp = [NSValue valueWithCGPoint:CGPointMake(5.3f, 2.6f)];
}
(However, it would probably make more sense to have methodCallWithObject just return a new object.)

How to check object is kind of block or not

How can we identify any particular object is kind of block or not?
for example,
NSSet *set =[NSSet setWithObjects:
#"name1",
#"name2",
[^{ /* ..... some code */ } copy],
nil];
How can we find out which object from set is kind of block?
There is a safer way to determine if something is a block without actually using private api or constructing a class using the private string name:
- (BOOL)isBlock:(id)item {
id block = ^{};
Class blockClass = [block class];
while ([blockClass superclass] != [NSObject class]) {
blockClass = [blockClass superclass];
}
return [item isKindOfClass:blockClass];
}
Wrap your block in a class of your own:
BlockWrapper *blockWrapper = [BlockWrapper wrapperWithBlock:^{ … }];
Check for the type and extract the actual block:
if ([obj isKindOfClass:[BlockWrapper class]]) {
codeBlock = [(BlockWrapper*)obj block];
}
There is no supported way to do this. You must keep track of what objects are blocks, and what their type signatures are.
Do you have a practical use case for a set of mixed strings and blocks?
It's possible, but I wouldn't recommend doing this, because NSBlock is not a public class and its name might change in the future:
if ([obj isKindOfClass:NSClassFromString(#"NSBlock")]) {
NSLog(#"It's a block!");
}
If you only have strings and blocks, just check ![thing isKindOfClass:[NSString class]]. i.e. invert your test.
Likewise, if you have strings, numbers and blocks, check that thing is not a string or a number, and in that case it must (by deduction) be a block. Either that, or your program is incorrect and will crash.
I suppose that ![thing isKindOfClass:[NSObject class]], while not technically correct (you don't have to subclass NSObject), will probably get you want you want.

checking if an array doesn't contain a certain object

is there a class available to check if an array doesn't contain an object?
I want to do something like
if [(myarray doesntContain #"object")]
is this possible
For NSArray use -containsObject::
if (![myarray containsObject:someObject]) {
// ...
}
I wrote an NSArray category to achieve these negated checks via instance methods, as you had originally requested.. The first is for an array-type set group of objects, the latter for a singular check. These return YES in the case that the array instance DOES NOT contain the passed object or objects. Why? Exclamation marks confuse me.
NSArray+Additions.h
-(BOOL)doesNotContainObjects:(id<NSFastEnumeration>)enumerable;
-(BOOL)doesNotContainObject:(id)object;
NSArray+Additions.m
-(BOOL)doesNotContainObjects:(id<NSFastEnumeration>)enumerable {
for (id x in enumerable) {
if ([self containsObject:x]) return NO; // exists, abort!
}
return YES; // it ain't in there, return TRUE;
}
- (BOOL)doesNotContainObject:(id)object {
if ([self containsObject:object]) return NO; return YES;
}
If you're dealing with an NSArray, your first port of call should probably be the Apple documentation for NSArray, and probably the method containsObject, there's an example in this question.