Objective-C self variable check - objective-c

I am reading the Cocoa Design Patterns books. In the books, after assigning the self variable, it is checked whether self is nil like below
if( nil != self){
// code
}
I have also seen another way of checking the self like
if( self ){
// code
}
Is there any benefit for using either of these techniques or is it just a matter of preference?
Thanks.

They're the same
The contents of an if block
if (expression) {
// contents...
}
are executed just in case the expression evaluates to a non-zero value.
This means that the code in the following if block
//the first if block
if (self) {
// contents....
}
will execute whenever self is non-zero.
Meanwhile, the contents of this if block
// the second if block
if (self != nil) {
// contents...
}
are executed whenever self != nil is non-zero.
The operator != returns 0 in the case that the two comparands (in this case self and nil) are identical and returns 1 in the case that the two comparands are not identical. So the code in the second if block will execute whenever self is not identical to nil.
But nil is #defined to be 0 in <objc/objc.h>. Thus the code in the second if block will execute whenever self is not identical to 0. This is exactly the same time that the code in the first if block executes: whenever self is non-zero.
The upshot
Since the two approaches result in exactly the same code being executed, there are no technical reasons to prefer one to the other. The most important stylistic consideration in this case is consistency in your initializers. Decide which style you prefer and use it everywhere.

Related

using performSelector in a c function to call delegate

Scenario
if (delegate && [delegate respondsToSelector:#selector(aboutTextUpdated:)]) {
[delegate aboutTextUpdated:aboutText];
}
to simplify this kind of checks in my project I created a couple of c functions as below and used them.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
id callSelectorOnDelegateWithObject(SEL selector,NSObject *delegate,id object)
{
if (delegate != nil && [delegate respondsToSelector:selector] == YES)
{
if (object != nil)
{
return [delegate performSelector:selector withObject:object];
}
else
{
return [delegate performSelector:selector];
}
}
return nil;
}
id callSelectorOnDelegate(SEL selector,NSObject *delegate)
{
if (delegate != nil && [delegate respondsToSelector:selector] == YES)
{
return [delegate performSelector:selector];
}
return nil;
}
#pragma clang diagnostic pop
they were called as below
callSelectorOnDelegateWithObject(#selector(aboutTextUpdated:), delegate, aboutText);
Problem
I get EXC_BAD_ACCESS error some times, but not in a reproducible manner. The exception occurred when the c function was called but before executing the first statement. When I replace the function call with actual if statement, then the error never occurs. To meet project deadline I went ahead with that change. But couldn't get this error out of my head.
What is causing the error?
More Background
The project uses ARC, minimum target is iOS 5.0
The project uses AFNetworking 1.* to get data from server, core data to save it in the app and NSNotification for inter app communication
The methods given to perform selector always return void
We would need to see the details of the crash to know more. My best guess is that there are occasional calls to callSelectorOnDelegateWithObject() where object is nil but the method identified by selector actually does take an argument. In that case, you're using just -performSelector:, not -performSelector:withObject:. So, the method receives garbage for its argument.
If some code called callSelectorOnDelegateWithObject() rather than callSelectorOnDelegate() then you should pass the object argument through unconditionally. The caller passing nil does not mean you can drop the argument. The nil probably (or, at least, possibly) is important.
That said, this whole approach doesn't seem like a good idea. I would not find this scheme simpler than the code snippet at the top of your question.
You can simplify that code snippet by not explicitly checking if delegate is non-nil. The -respondsToSelector: check will already return false if delegate is nil, because messaging nil always results in false.
Finally, you should never compare against YES (or TRUE, etc.). You're taking an expression which is already a boolean expression and then making it a compound boolean expression. Let me ask if you would ever write code like the following:
if (([delegate respondsToSelector:selector] == YES) == YES)
...
If you would not write that second == YES (and an infinite sequence of further comparisons to YES), then you should understand why you shouldn't have written the first.
Beyond that, any non-zero value is a true value. YES is only one such value. For any given method which returns a boolean value, you can't be sure that the true value it returns is actually YES as opposed to any other true value.

Is testing for self still necessary and/or meaningful? [duplicate]

This question already has answers here:
In Objective-C why should I check if self = [super init] is not nil?
(9 answers)
Closed 9 years ago.
A usual initialization sequence in an Objective-C instance (e.g. in the designated initializer) goes like:
- (id)initWithFrame: (NSRect)frame {
self = [super initWithFrame: frame];
if (self != nil) {
// Do your stuff.
}
return self;
}
This is a well known pattern, but is it really necessary to test if self is assigned? I mean, if something fails in the super method, wouldn't it rather raise an exception than just returning nil? Is it a safe pattern at all? What if the call to super had a problem but still returns a (random) pointer?
It's certainly a matter of defensive programming but it really looks exaggerating to have so many many tests for cases you know for sure that there's never a nil result. It makes of course a lot of sense to check self if you know that it can occur (which must be documented then).
Raising an exception is not reasonable behavior in an objective-c program when something goes wrong. Throwing exception should only used for critical, unrecoverable, programmer-error situations.
The correct way to signal error from an init method is to return nil and optionally fill in a passed NSError-pointer with more information. Testing if your super initializer returns nil prevents you from doing useless initialization, and helps avoid possible crashes like:
#implementation {
int _foo; // instance variable
}
- (id)initWithFrame: (NSRect)frame {
self = [super initWithFrame: frame];
if (self != nil) {
_foo = 2;
}
return self;
}
This will crash if the super initializer returns nil, because _foo = 2 is short-hand for self->_foo = 2, which would dereference a nil pointer. (Only message sends return nil when self is nil; accessing an ivar directly doesn't make that guarantee.)
Some classes, even Apple's own NS classes can return nil from an initializer, e.g. NSArray's and NSDictionary's initWithContentsOfFile: and initWithContentsOfURL: methods. Should those throw an exception instead? NO! They're easily detectable and easily recoverable cases. Throwing an exception would be nothing but a crutch for lazy programmers who can't be bothered to put in proper error-checking and a bother for those of us who do.
The question boils down to: Are there any (many) known classes that do return nil from an initializer?
I think there are few. Of course there are known cases (where the constructor often takes an NSError by reference) that have to return nil to point out an error.
But most other initializers either return the self argument or another instance of the class. If that's not the case it should be clearly expressed in the documentation, as code usually relies on object creation not failing.
So I think it's totally safe to omit the test for nil when you checked the superclass's behavior.
On the other hand the pattern is so omnipresent that co-developers might be confused about the omission and might point it out as an oversight. So if you plan to switch to a style without the condition it should at least be somehow communicated to your fellow developers.

Obj C - Is there a way to make a method return the method in which it is called?

I want to know whether there is the way to achieve the following requirement:
First, there is a methodA, which takes an input objA and check whether objA is valid for the method. If it's valid, then it returns an object objB. However, if objA is not valid, it just returns objA itself. Note that even if objA is valid, the returned objB may still be the same with objB.
Then, there is a methodB and in the method, methodA is called. If the input of methodA is valid, the program go on without error. However, if methodA is called with invalid input, then methodB should terminate (a.k.a return with a certain string signaling an error) to prevent future crash.
The current solution that I could think of is to create a (BOOL)methodAInputIsValid:(obj)input and in methodB there is:
if(methodAInputIsValid:input) {
obj objReturn = methodA:input;
}else{
//show error warning
return;
}
//continue doing something with objReturn and finally return some valid thing
A problem of the code is that (BOOL)methodAInputIsValid:(obj)input and methodA:(obj)input share a lot of code in common because there is a validity-test in methodA. So I want to use the validity-test more efficiently so that it will work for methodB and drop the (BOOL)methodAInputIsValid.
Here is one possible application that I could think of:
In a program the user is asked to enter a string that will direct the action of the program. However, the input string may need to be standardized such as converting all letters to lower-case and converting all single quotation to double quotation and auto-complete any missing right parenthesis or quotation marks. However, if the user is just entering nonsense that cannot be standardized, then the program should terminate and warn the user of the problem. The two methods are (BOOL)isStandardizeable:(NSString *)input and (NSString *)standardize:(NSString *)input. Because (NSString *)standardize already returns an NSString *, I can't make it to return another BOOL, right? So the following code is not achievable:
if(standardize:input){
NSString *result = standardize:input;
} else {
NSLog(#"unrecognizable input!");
return;
}
//continue...
Can anyone think of a way to do this?
Realistically, I'd just have methodA return nil if the input is not valid. This is a fairly common method to signal failure to a caller. If you really need the "identity" part of the method, just have callers do
id res = [... methodA:input];
if(res == nil)
res = input;

Objective-C block "retain cycle" warning, don't understand why

I've seen several other questions of the same form, but I either a) can't understand the provided answers, or b) don't see how those situations are similar to mine.
I'm writing a Category on UIView to recursively evaluate all the subviews of a UIView and return an Array of subviews passing a test. I've noted where my compiler warning occurs:
-(NSArray*)subviewsPassingTest:(BOOL(^)(UIView *view, BOOL *stop))test {
__block BOOL *stop = NO;
NSArray*(^__block evaluateAndRecurse)(UIView*);
evaluateAndRecurse = ^NSArray*(UIView *view) {
NSMutableArray *myPassedChildren = [[NSMutableArray alloc] init];
for (UIView *subview in [view subviews]) {
BOOL passes = test(subview, stop);
if (passes) [myPassedChildren addObject:subview];
if (stop) return myPassedChildren;
[myPassedChildren addObjectsFromArray:evaluateAndRecurse(subview)];
// ^^^^ Compiler warning here ^^^^^
// "Capturing 'evaluateAndRecurse' strongly in this block
// is likely to lead to a retrain cycle"
}
return myPassedChildren;
};
return evaluateAndRecurse(self);
}
Also, I get a bad_access failure when I don't include the __block modifier in my block's declaration (^__block evaluateAndRecurse). If someone could explain why that is, that would be very helpful too. Thanks!
The problem here is that your block evaluteAndRecurse() captures itself, which means that, if it's ever to be copied (I don't believe it will in your case, but in slightly less-trivial cases it may), then it will retain itself and therefore live forever, as there is nothing to break the retain cycle.
Edit: Ramy Al Zuhouri made a good point, using __unsafe_unretained on the only reference to the block is dangerous. As long as the block remains on the stack, this will work, but if the block needs to be copied (e.g. it needs to escape to a parent scope), then the __unsafe_unretained will cause it to be deallocated. The following paragraph has been updated with the recommended approach:
What you probably want to do here is use a separate variable marked with __unsafe_unretained that also contains the block, and capture that separate variable. This will prevent it from retaining itself. You could use __weak, but since you know that the block must be alive if it's being called, there's no need to bother with the (very slight) overhead of a weak reference. This will make your code look like
NSArray*(^__block __unsafe_unretained capturedEvaluteAndRecurse)(UIView*);
NSArray*(^evaluateAndRecurse)(UIView*) = ^NSArray*(UIView *view) {
...
[myPassedChildren addObjectsFromArray:capturedEvaluateAndRecurse(subview)];
};
capturedEvaluateAndRecurse = evaluteAndRecurse;
Alternatively, you could capture a pointer to the block, which will have the same effect but allow you to grab the pointer before the block instantiation instead of after. This is a personal preference. It also allows you to omit the __block:
NSArray*(^evaluateAndRecurse)(UIView*);
NSArray*(^*evaluteAndRecursePtr)(UIView*) = &evaluateAndRecurse;
evaluateAndRecurse = ^NSArray*(UIView*) {
...
[myPassedChildren addObjectsFromArray:(*evaluateAndRecursePtr)(subview)];
};
As for needing the __block, that's a separate issue. If you don't have __block, then the block instance will actually capture the previous value of the variable. Remember, when a block is created, any captured variables that aren't marked with __block are actually stored as a const copy of their state at the point where the block is instantiated. And since the block is created before it's assigned to the variable, that means it's capturing the state of the capturedEvaluteAndRecurse variable before the assignment, which is going to be nil (under ARC; otherwise, it would be garbage memory).
In essence, you can think of a given block instance as actually being an instance of a hidden class that has an ivar for each captured variable. So with your code, the compiler would basically treat it as something like:
// Note: this isn't an accurate portrayal of what actually happens
PrivateBlockSubclass *block = ^NSArray*(UIView *view){ ... };
block->stop = stop;
block->evaluteAndRecurse = evaluateAndRecurse;
evaluteAndRecurse = block;
Hopefully this makes it clear why it captures the previous value of evaluateAndRecurse instead of the current value.
I've done something similar, but in a different way to cut down on time allocating new arrays, and haven't had any problems. You could try adapting your method to look something like this:
- (void)addSubviewsOfKindOfClass:(id)classObject toArray:(NSMutableArray *)array {
if ([self isKindOfClass:classObject]) {
[array addObject:self];
}
NSArray *subviews = [self subviews];
for (NSView *view in subviews) {
[view addSubviewsOfKindOfClass:classObject toArray:array];
}
}

BOOL being set to 'NO' but succeeds for a check off == YES

.h
#property (nonatomic,assign) BOOL dontSendDelegate;
.m
#synthesize dontSendDelegate;
- (id) initWithSession:(AVCaptureSession *)aSession outputFileURL:(NSURL
*)anOutputFileURL
{
self = [super init];
if (self != nil)
{
self.dontSendDelegate = NO;
}
return self;
}
if (self.dontSendDelegate == YES)
{
NSLog(#"YES");
}
else
{
NSLog(#"NO");
}
Thats all my code in that class relating to the BOOL.
It always prints YES.
What is it that I'm not understanding? I expect it to always print NO.
EDIT
Used Xcode to search 'dontSendDelegate'
It only appears in the code I've shown. Which is copy and paste.
Changed it to an int and assigned 0 instead of the 'NO' and did the comparison == 1 instead of == YES and it works as you would expect. But I'm still lost as to why BOOL was not working.
Thanks for all the help and discussion about the problem.
When you put the mutable part of an expression (your bool instance variable) before a comparison operator such as ==, sometimes you have a typo where you write = instead, so you set the variable instead of compare it. Look for errors of this type.
Or always put the immutable value first, so in the code you have provided so far you would instead write
if (YES == self.dontSendDelegate)
That way, if you ever type one equal sign instead of two, the compiler will complain.
(from comments) When testing boolean variables, you don't need to use == at all. Just use if (self.dontSendDelegate) or if (!self.dontSendDelegate).
#GeorgFritzsche is correct. When this happens I override the setter and create a breakpoint. Then take a look at the stack on the left side of your screen and trace it down to the culprit. Most likely you are changing the value somewhere else in your program.