I have an NSMutableArray in my class containing Ingredient objects. I want to check whether the name property of any of the ingredients matches a string, but I can't get the syntax quite right.
I'm really missing Linq and predictates.
-(BOOL) hasIngredient:(NSString *)ingredientName{
for (Ingredient *ingredient in ingredients) {
//if([ingredient isKindOfClass:[Ingredient class]]){
if ([ingredient->name isEqualToString:ingredientName]) {
return YES;
}
//}
}
return NO;
}
The foo->bar syntax directly accesses instance variables. You shouldn't do that. The syntax to access a property is:
object.property
or:
[object property]
Accessing a property is always a method call. If you have a property foo and do #synthesize foo;, the compiler generates a method named foo and setFoo: (if the property isn't readonly).
So you should have something like:
#property(nonatomic,readonly) NSString *name;
Replace readonly with copy if you want the name to be changeable (the reason to use copy instead of retain is because you could pass a mutable string and then later modify that mutable string, which would sure yield unexpected results; you avoid that by copying).
Now your method becomes:
-(BOOL) hasIngredient:(NSString *)ingredientName{
for (Ingredient *ingredient in ingredients) {
if ([[ingredient name] isEqual:ingredientName]) {
return YES;
}
}
return NO;
}
Instead of [ingredient name] you can also write ingredient.name here, but I personally like the former better since the later is also used for accessing members of a struct which is "cheap" whereas accessing a property always involves a method call and thus is "more expensive". But that's just a matter of taste.
Change
if ([ingredient->name isEqualToString:ingredientName])
to
if ([ingredient.name isEqualToString:ingredientName])
Related
OK, this must have been asked before but I looked like mad and found nothing:
I have a simple array in my iphone app which I define like so:
#property (nonatomic, strong) NSArray *pages;
#synthesize pages = _pages;
I've seen this in Apples sample code and thought this is a nice short-cut for writing self.pages (i.e. _pages replaces self.pages) like so:
_pages = [[NSArray alloc] init];
but then Apple has this again (not exactly like this, but it appears as if they keep swapping randomly):
self.pages = [NSKeyedUnarchiver unarchiveObjectWithData:contents];
And finally:
[_pages release];
Which totally confuses me. What would be the difference between _pages and self.pages?
Thanks for your help.
_pages is the name of the object's ivar. pages is the property name which is different.
So, #synthesize pages = _pages; finally tells that pages is the property for the ivar _pages.
You will encouter the ivar direct access via _pages in initializers and dealloc methods. Every where else, the property name is used to get/set its value.
When you use a simple assignation :
_pages = ...
you simply set the instance variable.
When you use a property assignation :
self.pages = ...
It call a method synthesized automatically by the compiler (or defined by you) and for synthesizing this method, it checks the type of the property (retain, assign, ...) and writes code to match this type of property.
This difference comes from common naming and usage practices.
Both the instance variable and the property refer to the same object. The difference in naming is used for pointing out the difference between the ivar (_pages) and the property (pages).
The ivar is owned by the instances of the class and it's up to them to handle ownership operations for it (alloc, retain, release, etc.). Typically, these ownership operations take place in init and dealloc.
On the other hand, the property provides the 'designated' access point for the ivar. The property methods (the setter and getter) may perform additional operations required for the proper management of the ivar. So accessing the ivar directly (as a usage pattern) is not recommended, even within the owning objects. For example, a setter might be implemented like this:
- (void) setPages:(NSArray *)newValue {
[newValue retain];
// additional operations that you will miss if you use the ivar
[someObject someUsefulOperationThatIsReallyNeeded];
[pages release];
_pages = newValue;
}
_pages is the instance variable and pages is the property name. The property is accessed via the getter and setter methods pages and setPages: object.pages is equivalent to [object pages] or for your example `[self setPages:[NSKeyedUnarchiver unarchiveObjectWithData:contents]];
So the only actual object is the instance variable _pages and so only this can be memory managed.
The property and synthesiser code in effect give the same as this code (in practice there could be extra code for memory management and thread locking
#interface MyClass
{
...
NSArray *_pages
}
- (NSArray*)pages;
- (void)setPages:(NSArray*)newValue;
#end
#implementation MyClass
- (NSArray*)pages
{
return _pages;
}
- (void)setPages:(NSArray*)newValue
{
_pages = newValue; // Note in non ARC code there would be some memort managment here
}
#end
You can reference an #synthesized property either as instanceVariableName or as self.propertyName. The two names can be the same or different.
When you reference as instanceVariableName, and modify the value, none of the retain/copy logic of the associated property is applied -- you're just referencing the "raw" variable. When you reference self.propertyName, the retain/copy logic is applied, and, eg, if the property is declared with "retain" then the old value will be released and the new value retained.
When assigning an already-retained value (such as one from alloc/init) to a property, it's simpler (if this an initialization where the property was previously nil) to assign to instanceVariableName and skip the need to release the value (so that the net number of retains will be 1 at the end of the operation). But when assigning a value that is not retained (other than an autoreleased retain) to a property, you want to have the property's retain occur, so you'd use the self.propertyName notation.
Using a leading "_" for an instance variable that is also a property is a simple convention to keep these two apart, and avoid accidentally referencing one (by adding/removing self erroneously) when you meant the other.
I saw this post: How to sort an NSMutableArray of objects by a member of its class, that is an int or float
And had something similar, but I wasn't sure how it all works and was hoping for some guidance. I have an Array of Marker objects that have a Type ivar that takes on values of 0, 1, 2. I want to have a check box that says what to order by, 0, 1, or 2.
I started off by trying to doing something similar in my own method:
- (NSComparisonResult)Type:(id)otherObject {
if ([self Type] > [otherObject Type]) {
return NSOrderedAscending;
}
else if ([self Type] < [otherObject Type]) {
return NSOrderedDescending;
}
else {
return NSOrderedSame;
}
}
In my .h file:
NSInteger _type;
#property NSInteger Type;
I get the two warnings:
Ordered comparison between pointer and integer ('id' and NSInteger')
Method - Type not found (return type defaults to 'id')
I don't think I understand what is happening when you call the sort method. Thanks.
What happens if you're explicit about the input type being a YourObjectType * (or whatever your object is called) rather than id? To be completely safe you should check the type of the incoming object anyway (as it may not respond to 'Type' at all, or may return something else with the same selector), so you'd end up with:
- (NSComparisonResult)Type:(YourObjectType *)otherObject {
if(![otherObject isKindOfClass:[YourObjectType class]]) return NSOrderedSame;
if ([self Type] > [otherObject Type]) {
return NSOrderedAscending;
}
else if ([self Type] < [otherObject Type]) {
return NSOrderedDescending;
}
else {
return NSOrderedSame;
}
}
I'm basically making the same guess as highlycaffeinated, that the compiler is failing to correctly determine the return type of 'Type', but my guess is that it's because of an incorrect compiler prediction about the incoming object.
To explain the whole process:
When you ask NSArray to sortUsingSelector, it'll apply some sorting algorithm that requires it to be able to compare any two objects within it. When it needs to compare two objects, it'll send the selector you supplied, then use the result you return — so with Ascending/Descending you're specifying the order that the two objects would appear in if correctly sorted.
For example, if you had an NSArray filled with objects of type SillyObjectType and you issued a sortUsingSelector:#selector(compare:) then NSArray would apply some unspecified sorting algorithm that involved sending the selector compare: to instances of SillyObjectType. Each SillyObjectType is being asked "should you come before, after, or at an equal place to this other object?". It replies with NSOrderedAscending, Descending or Same.
This is one place where ObjC's dynamic dispatch gives a slightly different way of writing the thing than you'd use in e.g. C++. The selector will be sent to the objects in the array, so you should implement it on those objects. In each case the normal rules apply, so self will be that instance of that class.
It looks like you've defined Type as an ivar and not a property, therefore it won't be visible in otherObject. Expose it as a property and your comparison should work.
I am some what confused as to the difference between accessing an instance variable via self or just by name (when working inside the class).
For instance, take this class:
//In .h file:
#interface Register : NSObject {
NSString *mName;
}
- (id) initWithName:(NSString *) name;
//In .m file:
- (id) initWithName:(NSString *)name
{
if (self == [super init])
{
mName = name;
}
return self;
}
What's the difference between accessing the instance variable via
self.mName = name;
vs
mName = name;
Which isn't a #property and is not #sythenize'd.
Say it is this though, per this example:
//In .h file:
#interface Manange_My_ViewsViewController : UIViewController {
IBOutlet UILabel *countLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *countLabel;
//In .m file:
#synthesize countLabel;
- (void) updateLabel:(NSUInteger)count
{
countLabel.text = [NSString stringWithFormat:#"%d", count];
}
But say I accessed countLabel as:
self.countLabel
What would be the difference?
Edit: Third example per users' answer:
Say it the iVar wasn't an IBOutlet:
//In .h file:
#interface Fake : NSObject {
NSString *mVar;
}
#property (nonatomic, retain) NSString *mVar;
//In .m file:
#synthesize mVar;
mVar = #"";
VS
self.mVar = #"";
Or is it the same - that in the first we are accessing the actual instance variable and in the second we're actually going through the auto created setter (via #synthesize)?
Thanks all!
Edit: Update in response to Peter Hosey ...
So your thinking the convention of mVarName is bad? I took that from my C++ days.
But what about the case when you do?
-(void) someMethod:(int) x
{
x = x;
}
You can't do that (Say 'x' is also a class variable)
But you can do:
-(void) someMethod:(int) x
{
mX = x;
}
But your saying its better to do:
-(void) someMethod:(int) x
{
self.x = x;
}
What's the difference between accessing the instance variable via
self.mName = name;
vs
mName = name;
The first is property access syntax. It translates to an accessor message to the object (in this case, self). That is, that statement implicitly translates to this message expression statement:
[self setMName:name];
(Awkward accessor names like that are why “mName” is a poor name for a property. There is property declaration syntax to work around that, letting you name the property “name” and your instance variable “mName” and map one to the other.)
The second example directly accesses the instance variable—no accessor message.
Which isn't a #property and is not #sythenize'd.
Say it is this though, …
If no property named “mName” is declared for a class, then you can't use property access syntax to access a property by that name on an instance of that class.
And it doesn't matter whether you synthesize the accessors, hand-wave them to a superclass with #dynamic, or define them yourself. That's how the object will respond to the accessor message, but the accessor message the compiler generates will be no different (since a property access could just as easily come from outside the class as from inside it).
Say it the iVar wasn't an IBOutlet:
That doesn't matter. IBOutlet only means anything to IB. Everything else doesn't care.
In fact, IBOutlet is currently just a macro that expands to nothing. After your code gets preprocessed, the word “IBOutlet” is no longer there, so the compiler never sees it. That's how little a difference it makes to anything but IB: None at all.
Edit in response to question edit
I said mName is bad as a property name, because of the accessor names that follow from it. The name of an instance variable is a separate issue, particularly since the property and ivar don't have to have the same name.
For a variable, be it an instance variable or a local variable, the choice of name or m_name or mName is purely a style choice.
someMethod: is generally the accessor, setX:. Within that method, self.x = x, which is [self setX:x], causes infinite recursion. So don't do that.
When someMethod: isn't the accessor (or init or dealloc), using the property is just fine and generally preferable. However, in that case, you're not likely to give one of its arguments the same name as an instance variable. When such a case could occur, name the local variable more specifically, because its purpose is more specific. This, too, is a style issue.
When it is the accessor, I name the local variable newX, having named the instance variable the same as the property, x. This is my own personal style; as I said, naming the property x, the ivar mX, and the local variable x is fine too (aside from the excessive brevity of this example).
OK, first off is the basic difference:
mVar = var;
This is just changing a value. That's it.
self.mVar = var;
This is equivalent to:
[self setMVar:var];
In other words, one invokes a method, the other does not. Using the #property syntax can give you some really neat benefits. For example, you get key-value coding compliance for free. That means that another object can observe this object's mVar property, and be automatically notified whenever it changes, without you doing anything. You don't get this if you just access the ivar directly. (Unless, of course, you implement it yourself. But why would you do that?)
You also get semi-free memory management. If you declare a property as (retain), then you don't have to [newValue retain] yourself. The synthesized method will do this for you (in both cases, you'd still have to [ivar release] in your dealloc method).
You also can get some degree of thread safety. If you don't declare a property as (nonatomic), then it is (by default) atomic (although that keyword does not exist; it's implied). That means that reading/updating the value of the property is an atomic operation. If you were to just access the ivar directly, you'd have to implement the atomicity yourself with a lock.
Basically, using the synthesized methods gets you some really neat stuff for free. The only reason I'd say to not use the #property syntax is if you have irrefutable evidence that invoking those methods is a bottleneck in your code. However, you'll be really hard pressed to come up with a situation where that would be the case.
First of all, with a read-only property--which an IBOutlet essentially is--it does not matter as much.
The key difference is that the property is actually calling the accessor method while the instance variable is being accessed directly.
Thus, for setting a retain property, using self and the accessor will release the old object and retain the new one. Setting the instance variable directly will NOT impact the retain counts of any objects.
Using #synthesize will generate standard accessors for you.
The key reason to use properties is that, since they are accessors, they can be read and/or modified from outside the class.
I've noticed in some of the examples ive seen that you will set a engine( class variable ) to a _engine ( ivar ). I don't get it. What's going on here?
Here is an example of what I'm saying:
#synthesize engine = _engine, delegate = _delegate
This syntax maps a property to an instance variable (ivar) with a different name.
So:
#synthesize engine = _engine;
will create property accessor methods that access the _engine ivar instead of engine. You can still access the propery as:
object.engine
More info in the Apple developer documentation on properties (section Property Implementation Directives)
The author wanted to make sure that there was no confusion between accessing the ivar directly and accessing via the setter/getter. If the names are the same, the usual case, it is easy to write:
engine = 0 instead of self.engine = 0; For an ivar that needs to be retained such as NSString this can cause errors in the retain counts.
There is also historic precedence of naming ivars with a leading "_", "m" or "f" so they wpuld be readily recognized as ivars.
The #synthezise keyword tells the Objective-C compiler to generate a getter and a setter method for your property. If you have defined:
#property(copy,nonatomic) NSString* name;
Then #synthesize name; will create these two methods for you, so that you do not have to implement them:
-(NSString*)name;
{
return name;
}
-(void)setName:(NSString*)newName;
{
if (name != newName) {
[name release];
name = [newValue copy];
}
}
By default the name of the instance variable that is used as the backing store for the synthesized property is named the same as the property. This is not always what you want, and you can then synthesize as #synthesize name = _otherName; to tell the compiler to instead generate this code for you:
-(NSString*)name;
{
return _otherName;
}
-(void)setName:(NSString*)newName;
{
if (_otherName != newName) {
[_otherName release];
_otherName = [newValue copy];
}
}
The reason you usually prefix the instance variables that are used as backing stores for properties with a underscore character '_' is to make help you to remember not to access them directly.
If the name of the ivar does not exactly match the name of the synthesized var then you need to map the ivar to the var. You might want to do this if you like prefixing your ivars with an underscore.
It's a month ago I was reading a line about that. I am not sure, but I think that if I call self.myInstanceVariable then it uses automatically getters/setters, but if I would call directly myInstanceVariable = #"Foo" for example, then I would bypass any getter/setter which would be really, really, reeeaaallly bad. Right/wrong?
EDIT: I tried this in XCode.
The implementation looks like this:
#implementation Test
#synthesize name;
+ (Test*)testWithName:(NSString*)name {
Test* test = [self alloc];
test.name = name;
return [test autorelease];
}
- (void)setName:(NSString*)newName {
NSLog(#"SETTER CALLED!!");
if(name != newName) {
[name release];
name = [newName retain];
}
}
- (NSString*)name {
NSLog(#"GETTER CALLED!!");
return name;
}
- (void)doWrongThing {
NSString *x = name;
NSLog(#"doWrongThing: %#", x);
}
- (void)doRightThing {
NSString *x = self.name;
NSLog(#"doRightThing: %#", x);
}
The test code looks like that:
Test *t = [Test testWithName:#"Swanzus Longus"];
//NSLog(#"%#", t.name);
[t doWrongThing];
[t doWrongThing];
[t doWrongThing];
[t doRightThing];
So after launching this code in another method (I just used an existing project ;) ), I received this output in the console:
2009-05-01 19:00:13.435 Demo[5909:20b] SETTER CALLED!!
2009-05-01 20:19:37.948 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.949 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.949 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.950 Demo[6167:20b] GETTER CALLED!!
2009-05-01 20:19:37.965 Demo[6167:20b] doRightThing: Swanzus Longus
Like you see, you MUST use self.instanceVariableName in order to use the getters and setters (or you do the call in brackets, works too).
Confusion Alert: You must only use self if you hack around in a method of the object from which you want to access an instance variable. From the outside, when you call someObjectPointer.someInstanceVariable, it will automatically access the getters and setters (yep, I tried that out too).
Just thought someone would be interested in a little case study ;)
That is correct. If you directly use the variable, bypassing the getter/setter you could create bugs. The getter/setter may be responsible for retain and/or releasing the object as well as other things. This could result in crashes/memory leaks etc.
If you are aware that you are bypassing the getter/setter and take the right precautions, there is nothing wrong with accessing the variable directly.
Jesse has some good insight (+1 to you, sir).
The only circumstance under which I would consider explicitly calling the underlying member variable directly (thus bypassing the getter/setter) is when I have written the getter/setter myself, and know exactly what it is and isn't doing, and 99% of those times is when I'm just initializing the member in my constructor.
Just read the documentation
First, this is incorrect
Test* test = [self alloc];
correct is
Test* test = [[self alloc] init];
Second, if you write
#synthesize name;
methods
- (void)setName:(NSString*)newName
- (NSString*)name
will be generated(!! dot-syntax is just syntax-sugar !!) automatically
Third, when you write
myvar.itInstanceVariable
it translates to
[myvar itInstanceVariable]
and
myvar.itInstanceVariable = newValue
translates to
[myvar setItInstanceVariable:newValue]
About your comment, when you declare you property in that way
#property(nonatomic, retain) MyType *myVar;
and write in implementation
#synthesize myVar
it creates two methods
- (MyType*)myVar {
return myVar;
}
- (void)setMyVar:(MyType*)newVar {
if (myVar != newVar) {
[myVar release];
myVar = [newVar retain];
}
}
so you don't need to worry about reteaning/releasing
Yes, the property syntax calls the setter. In almost all cases, this is what you want, since it handles a lot of memory management correctly by default. Also, the property name, ivar name and getter/setter names can also all be different, so you may find cases where it doesn't look like self.myInstanceVar.
Also, just as a side note, you may or may not know this already, but there's no point to synthesizing a property if you're just going to write all the accessor methods anyway.