Ok I think my understanding of properties in objective c may not be what I thought it was.
In my program I have a singleton that contains my class.
In my class during the init I assign a value from the singleton to my property.
I then assign a value to a property of that property.
However it does not keep the value and when I do a compare of the value in the singleton nothing has changed. What is going on here? Any ideas?
#interface MainGameLoop : NSObject {
MapData *mapData;
}
#property (retain) MapData *mapData;
-(id) init
{
self = [super init];
GlobalVariables *sharedManager = [GlobalVariables sharedManager];
self.mapData = sharedManager.mapData;
return self;
}
In a function of my class:
works:
sharedManager.mapData.currentPlayer = newCurrentPlayer;
does nothing:
self.mapData.currentPlayer == newCurrentPlayer;
self.mapData.currentPlayer == newCurrentPlayer;
Are you sure that you want two equal signs there? That statement is syntactically correct and will evaluate to either true or false.
== is a Boolean operator, while = is an assignment operator. Like what Dave said, if you are using an if statement such as if (self.mapData.currentPlayer == newCurrentPlayer) {…}, you would want to use == because it would evaluate to true or false, while = would be used to set the value of a variable, which is what I think you are trying to do.
If it's any consolation, I've made that mistake too many times to count…
Something that I do is to use NSLog() or printf() to make sure that each step is working correctly.
Related
I came across a conditional if statement in Objective-C:
self.frontCardView = self.backCardView;
if ((self.backCardView = [self popPersonViewWithFrame:[self backCardViewFrame]])) {
// Fade the back card into view.
...
}
Basically:
if ((self.backCardView = self.popPersonViewWithFrame(self.backCardViewFrame()))) {...}
This sets "self.backCardView" to the return value of
"-popPersonViewWithFrame:". In C (and Objective-C), the result of an
assignment is the assigned value.
In this case, the result of the expression "(self.backCardView = [self
popPersonViewWithFrame:self.backCardViewFrame])" the return value of
"-popPersonViewWithFrame:".
If the return value is "nil", then the conditional is not executed (since "nil" is a false value).
If I try to do the same thing in Swift:
self.frontCardView = self.backCardView
if ((self.backCardView = self.popPersonViewWithFrame(self.backCardViewFrame()))) {
// Fade the back card into view.
...
}
I get an error in compilation:
Type '()' does not conform to protocol 'LogicValue'
Swift was specifically designed to not allow testing an assignment in a conditional for safety reasons (people accidentally using one = instead of two). The result of an assignment operator is always void () like the error says.
Assign, then check for nil separately.
self.frontCardView = self.backCardView
self.backCardView = self.popPersonViewWithFrame(self.backCardViewFrame())
if self.backCardView != nil {
// Fade the back card into view.
// ...
}
() is simply a typealias for void, which is what assignments return in Swift. As Bryan suggested, just put the assignment outside of the condition.
The condition isn't a condition, so like Bryan Chen said, do the assignment outside of the condition, but assign it to another variable. In the condition, then, check whether that variable is equal to backCardView, like so:
frontCardView = backCardView
let poppedView = self.popPersonViewWithFrame(self.backCardViewFrame())
if backCardView == poppedView {
// Fade the back card into view.
...
I am taking a warning from Xcode. Here is the code
DeviceList *dList = (DeviceList* )[[User thisUser] devices];
[dList getListId];
The warning states that instance method -getListId is not found. However the method exists in my source code
- (NSString*) getListId
{
T
if ( ... != nil)
{
return ...;
}
else
{
return #"";
}
}
I cannot figure out what the problem is when I am calling the method.
have you added a declaration for this method in the .h file, and if so, have you imported the .h into the file you are trying to call this method?
this error is basically the compiler saying it can't find the method declaration, so it doesn't know what to expect the return type to be.
in your DeviceList.h , make sure you have
#interface DeviceList : Parent
- (NSString*) getListId;
..
..
#end
the warning occurs when your method is not declared in your header file and you try to call it outside your (self) class.
I am checking if an object I am getting back from the NSURLConnectionDataDelegate is the same object that I originally created. What I have been doing is:
// TESTING TO SEE IF THE RETURNED OBJECT IS THE SAME ONE I CREATED
if(connection == [self connectionPartial]) {
But was just curious is this is the same as doing:
if([connection isEqual:[self connectionPartial]]) {
It's not the same.
if(connection == [self connectionPartial]) {
This compares the address of the objects, eg. if the pointers point to the same instance.
if([connection isEqual:[self connectionPartial]]) {
This compares the contents of the objects. For instance for two separate NSString instances, this will return YES as long as the string content is the same:
NSString *s1 = #"Something";
NSString *s2 = #"Something";
BOOL sameInstances = (s1 == s2); // will be false, since they are separate objects.
BOOL sameContent = [s1 isEqual:s2]; // will be true, because they both are "Something"
The first snippet compares the values of the pointers themselves, just as if they were any primitive type like an int. If the addresses are the same, the expression will evaluate true.
The second sends the message isEqual: to one of the connection instances. Any class can override isEqual: to define "equality" with another instance. It's entirely possible for a class's implementation of isEqual: to be:
- (BOOL)isEqual: (id)obj
{
return arc4random_uniform(2) ? YES: NO;
}
So, no, for almost all classes they are not equivalent. (NSObject, which has the "default" implementation of isEqual:, uses the objects' hashes, which, again by default, are their addresses.)
It sounds like using the equality operator, ==, is correct in your case.
Are there any difference between following ways to init self?
First:
- (id)init {
self = [super init];
if (self) {
}
return self;
}
Second:
- (id)init {
if (self = [super init]) {
}
return self;
}
I like to use second way to init self. But I often see the first way when I create a new class by Xcode, it will generate those codes automatically. I am afraid the second way will make some errors in some condition which I don't know.
Nope, they are the same.
The second method is just missing out the first assignment of self
Another way you might come across is this:
- (id)init {
if (!(self = [super init])) {
return nil; // Bail!
}
// Further initialisation
return self;
}
This puts the exceptional condition in the if statement, and keeps the code that you expect to run normally (the Happy Path) closer to the left margin.
In C and most(if not all) languages these two are same.
First
a = b;
if (a) {}
Second
if (a = b) {}
First one is just using one more line.
However, they are not same as
if (a == b) {}
They’re equivalent and you can safely use either of them. Some people prefer not to use
if (self = [super init])
because it is a tad overloaded: it means ‘assign the return value of [super init] to self, and then evaluate self as a (boolean) condition’.
At first glance, one could misread that code, interpreting the assignment operator = as being the equality relational operator ==, i.e., ‘compare self to the value returned by [super init]’, which is not the case.
This can be particularly confusing for programmers that are new to C. Not every programming language allows assignments in expressions, that is, assignments must be in a separate instruction.
Both are functionally equivalent but using assignments where conditional expressions are expected is discouraged as bad programming practice because it's usually accidental, e.g:
if (myVar = 5) {
printf("The variable was 5\n");
}
When you actually meant to write:
if (myVar == 5) {
...
However the Objective-C init code is usually an exception to this because it's a well known sequence and repeated a lot, so for convenience some people may choose to write the assignment within the conditional expression.
I have this inside a custom UIActionSheet class
if (otherButtonTitles != nil) {
[self addButtonWithTitle:otherButtonTitles];
va_list args;
va_start(args, otherButtonTitles);
NSString * title = nil;
while(title = va_arg(args,NSString*)) { // error here
[self addButtonWithTitle:title];
}
va_end(args);
}
I have this error
! using the result of an assignment as a condition without parentheses
pointing to this line
while(title = va_arg(args,NSString*)) {
why is that?
thanks.
This is probably not an error as you said, it's a warning.
The compiler is warning you that you should surround assignments within parentheses when it is within a conditional to avoid the ol' assignment-when-you-mean-comparison mistake.
To get past this rather pedantic compiler warning, you can simply surround the assignment within another pair of parentheses:
while((title = va_arg(args,NSString*))) {
//...
}
It should be a warning and not an error. It's trying to warn in case you're using = but you meant ==.
In this case, you're not meaning to use == because you're calling va_arg() multiple times to iterate through otherButtonTitles and assigning it to the temp var title, so just add another set of parentheses. The warning will go away.
while((title = va_arg(args,NSString*))) {
compiler thinks that you're doing assignment by mistake, hence suggesting this error. You should wrap your statement into ONE MORE PAIR of parenthesis like this:
while((title = va_arg(args,NSString*)))
Then compiler first will evaluate the assignment, then the result of that assignment will be passed into the while condition
It does seem a little picky, but have you tried:
while((title = va_arg(args,NSString*)) != NULL)
?