'If' conditional works with NSLog but not without? Objective-C - objective-c

I hope this question is some what self explanatory.
This works, returns YES and NO: note the NSLog()'s
- (BOOL)dateTestCourse:(NSDictionary *)listing {
BOOL result = ([self exammpleTest] == 0) ? YES : NO;
if (result) {
NSLog(#"Passes Test");
return YES;
}
NSLog(#"Failed Test");
return NO;
}
But below always return YES? Only difference is no NSLog();
- (BOOL)dateTestCourse:(NSDictionary *)listing {
BOOL result = ([self exammpleTest] == 0) ? YES : NO;
if (result) {
// NSLog(#"Passes Test");
return YES;
}
// NSLog(#"Failed Test");
return NO;
}
Is this something to do with C? I have no idea? I might expect it always to return NO (if I shouldn't be breaking in the conditional), but surely that would return YES.
I know I should be returning result in the above examples, but I'm curious to know why.

These two blocks of code should be running the same. Are you perhaps doing a find/replace all on NSLog? That could be causing issues elsewhere, say with the exammpleTest(sic) method.
Also, the ternary operator on the second line is redundant, consider reducing that line to:
BOOL result = ([self exammpleTest] == 0);

Related

What's really happen here?

if ([self errorIsServerError:error] || [self errorIsBadRequest:error] || [self errorIsNetworkError:error]) {
return YES;
}
The methods errorIsServerError:, errorIsBadRequest:, and errorIsNetworkError: all return the BOOL YES or NO.
But I don't understand the syntax. Is it:
if (YES || YES || YES) { return YES; }
?
|| is the equivalent to saying 'or'. So your code is returning true if any of the values are true. This is what it's saying :
if ([self errorIsServerError:error] or [self errorIsBadRequest:error] or [self errorIsNetworkError:error])
If any of those are true then
{
return YES;
}
Each of those returns YES if that particular categorization applies to the given error. If the error is a server or network error, or a bad request, the method will return YES.
You could look at it like this:
if ([self errorIsServerError:error]) {
// The error is a server error
return YES;
} else if ([self errorIsBadRequest:error]) {
// The error is a bad request
return YES;
} else if ([self errorIsNetworkError:error]) {
// The error is a network error
return YES;
}
In either case, it will return yes if the error is any of those types. It will also return YES if it is two or all of those types (|| is the logical (inclusive) "or" operator).
If it's none of the types, your method will continue until it hits another return statement.
It's not really clear what you're asking, but in general, you're probably expecting none of those errors to come through, meaning this if condition will evaluate false and your program can go on its way.

Checking to see if ObjectForKey exists [duplicate]

Most of the examples I found on the net write this:
if(x != nil)
// ...
Is there any problems with this?
if(x)
// ...
I tried both in a simple program and couldn't found any difference.
In Objective-C, nil is defined as a value called __DARWIN_NULL, which essentially evaluates to 0 or false in if-statements. Therefore, writing
if (x == nil) is the same as writing if (!x) and writing if (x != nil) is equal to if (x) (since comparing to false creates a negation, and comparing to true keeps the condition the same).
You can write your code either way, and it really depends on which you think is more readable. I find if (x) to make more sense, but it depends on your style.
It's like comparing if (someCondition == true) versus if (someCondition).
It all depends on you, and who's going to be reading the code.
Edit: As Yuji correctly mentions, since Objective-C is a superset of C, any condition that evaluates to a value other than 0 is considered to be true, and therefore, if someCondition in the example above were to evaluate to an integer value of, say, -1, comparing it to true would result in false, and the if-statement would not be evaluated. Something to be aware of.
Both
if (x != nil)
and
if ( x )
are equivalent, so pick the variant that in your opinion makes your code more readable for you (and others who will read and support your code)
Both are the same and this is a style question and it boils down to whether you prefer:
if (something) { ... }
versus
if (something != nothing) { ... }
I have always found #1 more clear but #2 is used extensively in documentation and hence the field so it is better to both know both forms and adapt to what a project uses and be stylistically consistent.
The best and safe way to check nil is
Make a common method, and add all these null :
+ (NSString *)trimWhiteSpaceAndNewLine:(NSString *)string {
NSString *stringSource = [NSString stringWithFormat:#"%#",string];
if ([stringSource isEqualToString:#"(null)"]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isEqualToString:#"<null>"]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isEqualToString:#"<nil>"]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isKindOfClass:[NSNull class]]) {
stringSource = #"";
return stringSource;
}
if ([stringSource isEqualToString:#""]) {
stringSource = #"";
return stringSource;
}
if (stringSource == nil) {
stringSource = #"";
return stringSource;
}
NSString *stringFinal = [stringSource stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
return stringFinal;
}
And check
NSString *strUuid = [Common trimWhiteSpaceAndNewLine:[dict valueForKeyPath:#"detail.uuid"]];
if (![strUuid isEqualToString:#""]) {
// do your stuff
}

Can't validate null string in Objective-C

I have the following code:
NSString *content = [[NSUserDefaults standardUserDefaults] stringForKey:#"mykey"];
NSLog(#"string is %#",content);
if ([content stringIsEmpty]){
NSLog(#"empty string");
}else{
NSLog(#"string is not empty");
}
stringIsEmpty is class category on NSString:
- (BOOL ) stringIsEmpty {
if ((NSNull *) self == [NSNull null]) {
return YES;
}
if (self == nil) {
return YES;
} else if ([self length] == 0) {
return YES;
}
return NO;
}
The output is:
string is (null)
string is not empty
How could it be null and not empty at the same time?
What happens is that:
[content stringIsEmpty:YES]
will return false (NO), when content is nil. So your code will take the
NSLog(#"string is not empty");
branch. This would be better:
if (content && [content stringIsEmpty:YES]){
...
A better way of doing this would be reversing the semantics of the method:
if ([content stringIsNotEmpty]) {
this would work finely because when content is nil it would return NO, when it is not nil, it would execute your method.
EDIT:
In Objective-C, sending a message to nil is legal and by definition will evaluate to nil. Google for "objective c sending message to nil".
In another language (C++), your code would crash (actually undefined behaviour, but to make things simple).
I use a small function to test for emptiness. It works on more than just strings:
static inline BOOL isEmpty(id thing) {
return thing == nil
|| ([thing respondsToSelector:#selector(length)]
&& [(NSData *)thing length] == 0)
|| ([thing respondsToSelector:#selector(count)]
&& [(NSArray *)thing count] == 0);
}
I usually import it in my pch file - you can see it along with attribution: https://gist.github.com/325926
As #sergio has already pointed out - when your string is nil you can't send it messages that test it for nil-ness - as sending messages to nil will do nothing for void methods, and return nil where the method returns something.
also
you are calling your method with a parameter
if ([content stringIsEmpty:YES])
but your method declaration doesn't take one:
- (BOOL ) stringIsEmpty {
What's that all about?
You have to check for the 'content == nil' case outside of the method.
If you want to be able to call just one method, change the method to something that tests for a positive, such as "stringHasContent", returning YES if self.length > 0.

Bool function for xcode

I am practicing some bool functions and I seem to be stuck any help will be appreciated. I must be making some little mistake.
-(BOOL) checkForWin
{
if ([[dictionary valueForKey:[cowsShuffled objectAtIndex:cowsCard]] intValue] == 2{
return YES;
}
}
-(void) moo
{
if (checkForWin == YES) {
NSLog (#"foo");
}
}
You need to call the method (not function), and you don't need to compare to YES. The if statement does that implicitly:
if ([self checkForWin]) …
Also note that checkForWin has a problem: it doesn't return anything if the if statement fails. It should be simply:
- (BOOL)checkForWin{
return [[dictionary valueForKey:[cowsShuffled objectAtIndex:cowsCard]] intValue] == 2;
}
Footnote: Strictly speaking, if (x) … isn't exactly the same as if (x == YES) …. It's actually closer to if (x != NO) …, but of course that's the same thing for most intents and purposes (and those for which it isn't are largely pathological).
Your method call is wrong. You call a method like this: [object method].
In your case [self checkForWin].

Anyway to make a (wrapping) NSTextField write a carriage return upon pressing return key?

I want to use a wrapping text field that can potentially contain carriage returns in my app. Is there any way to force the NSTextField object to write a carriage return into the text area instead of sending its action to its target when the Return key is pressed?
This is covered in Technical Q&A QA1454, which also enumerates reasons why one would use NSTextField instead of NSTextView in this case.
You can implement the following method in the text field delegate:
- (BOOL)control:(NSControl*)control
textView:(NSTextView*)textView
doCommandBySelector:(SEL)commandSelector
{
BOOL result = NO;
if (commandSelector == #selector(insertNewline:))
{
// new line action:
// always insert a line-break character and don’t cause the receiver
// to end editing
[textView insertNewlineIgnoringFieldEditor:self];
result = YES;
}
return result;
}
Okay, I figured out one way to do it, but this very well may not be the best (or even a good) way. I subclassed NSTextField, and overrode -textShouldEndEditing: like so:
-(BOOL)textShouldEndEditing:(NSText *)textObject {
NSEvent * event = [[NSApplication sharedApplication] currentEvent];
if ([event type] == NSKeyDown && [event keyCode] == 36) {
[self setStringValue:[[self stringValue] stringByAppendingString:#"\n"]];
return NO;
}
else {
return [super textShouldEndEditing:textObject];
}
}
I found a combination of Sean and Bevarious worked best for me. Sean's answer assumes that the new line is always wanted to be added to the end (instead of for instance where the user's cursor is placed).
-(BOOL)textShouldEndEditing:(NSText *)textObject
{
NSEvent * event = [[NSApplication sharedApplication] currentEvent];
if ([event type] == NSKeyDown && [event keyCode] == 36)
{
[textObject insertNewlineIgnoringFieldEditor:nil];
return NO;
}
else
{
return [super textShouldEndEditing:textObject];
}
}
Swift version:
override func textShouldEndEditing(textObject: NSText) -> Bool {
let event = NSApplication.sharedApplication().currentEvent
if event?.type == NSEventType.KeyDown && event?.keyCode == 36 {
self.stringValue = self.stringValue.stringByAppendingString("\n")
return false
} else {
return super.textShouldEndEditing(textObject)
}
}