I know that the . is a shortcut for a setter. Sometimes, I use that kind of code:
cell.textLabel.text = [NSString stringWithFormat:#"this is row %i", indexPath.row];
This works as expected, but I was wondering, is it better (or more correct maybe?) to write
cell.textLabel.text = [NSString stringWithFormat:#"this is row %i", [indexPath row]];
Or, in other words, should I use the dot syntax only with the = operator, like
aTextField.text = #"whatever";
Any links/docs are welcome, thanks :)
PS. In case you didn't see the tag, I'm talking about iOS here.
Dot (.) is not only a shortcut for setter, it's shortcut for getter too. You can use dot for getter too. There is no problem, neither this is bad practice. From Obj-C 2.0 programming guide, "You can use the dot syntax to invoke accessor methods using the same pattern as accessing structure elements. The dot syntax is purely “syntactic sugar”". Note that, it is saying about accessor method, not only setter.
It's a matter of taste.
I prefer not to use the dot syntax for various reasons:
When using dot syntax, it's much harder to find only the places in your code where you set an value. Search for setValue: is much easier than searching for .value
As a long time C programmer, my brain is wired to associate the dot syntax with accessing struct members. I find it rather hard to get used to the dot syntax in a different scope.
The setXY: syntax close follows the natural language much closer. Makes reading someone else's code so much easier.
"." is a shortcut for accessing a #property (which may, by the way, be readonly). From the syntax point of view whether this is a getter or a setter depends on the operand position:
self.enabled = NO; // setter
BOOL isEnabled = self.enabled; // getter
self.selected = self.enabled = NO; // this is OK too
It's coding style so neither is better.
I would note two things though.
As a long time Objective C code I prefer the [indexPath row] as it is consistent with the rest of the code and for a set I would use [aTextField setText:#"whatever"]
But if you need to use the . notation for keypaths the accessing the same variable via method notation in the same piece of code will seem odd.
Apple documentation says
Objective-C provides a dot (.) operator that offers a compact and convenient syntax you can use as an alternative to square bracket notation ([]s) to invoke accessor methods.
and
myInstance.value = 10;
printf("myInstance value: %d", myInstance.value);
The dot syntax is purely “syntactic
sugar”—it is transformed by the
compiler into invocation of accessor
methods (so you are not actually
accessing an instance variable
directly). The code example above is
exactly equivalent to the following:
[myInstance setValue:10]; printf("myInstance value: %d", [myInstance value]);
Using the dot syntax is not coding style or a matter of taste!
The dot syntax is for accessing properties. The message sending syntax is for dispatching methods. They are conceptually two different things. Legacy and backwards compatibility to Objective-C 1.0 unfortunately makes them interchangeable, which has caused allot of confusion.
Weather to user the dot-syntax or not is dead simple:
If a public header declares something as property, then access it as a property using the dot-syntax, as the author of the interface explicitly intended!
If a public header declares something as a method, then access it using the message sending syntax, as the author of the interface explicitly intended!
Make NO exceptions.
The hard question is, should you declare something as a property, and thus tell your clients that doit-syntax should be used, or should you declare a method? The simple answer is:
Use properties for states (is something).
Use methods for behaviors (do/calculate something).
Another rule of thumb is that properties should be self-contained, there should be no other way to change the value of the property but to set the property itself. This is Not a hard rule, use common sense, many sensible exceptions exist. For example a hidden property that can be changed with setHidden:animated: method.
Related
According to the Apple guideline , seems it is confusing, e.g. for method viewWithTag
In Java, I would have a method called
getViewByTag // Java version, equivalent to viewWithTag in Obj-C
But I also found there are some method like objectForKey, so why not just use objectWithKey instead?
getObjectByKey or just get // Java version, equivalent to objectForKey,
// but why not objectWithKey? Or not viewForKey above?
I actually think it is much simpler than what most answers think. I think it has less to do with complex programming language specifics, and has more to do with the uniqueness of the object in question.
When you say viewWithTag:, you are asking the UIView for any view that has that tag. There might be several. The UIView will return one of 'em.
However, objectForKey: (to me) sounds like there should be a single object (or nil) associated with that key. So, the key kinda exists and is bound (tightly coupled) to a single object.
EDIT:
There is an answer mentioning the existence of "by", which further implies how the convention has nothing to do with programming language complexities. It's just natural English.
NSString's stringByAppendingString:, for example, uses by, only because the function is written with a the verb appending. You can't say withAppending, that's bad English.
From my observation
While setting/getting the objects, you use WITH.
e.g. For setting of NSMutableArray object
- (id)initWithCapacity:(NSUInteger)numItems
While setting/getting the properties for objects, you use FOR.
e.g.For setting value for property of type NSMutableDictionary
- (void)setValue:(id)value forKey:(NSString *)key
Hope this helps in clearing your doubt
It seems like with is used for properties that directly belongs to an object. A UIView has a tag property so viewWithTag:14 could be rephrased as "Find the view whose tag property is 14".
When you put an object in a dictionary, associated to a key, this key is not necessarily part of the object itself. objectForKey:#"foo" is a way to say "Look for an object that's linked to the key "foo".
The Apple guidelines do not make any such claims as to when to use for or with. The point of the coding convention is to indicate what the types of the arguments may be and to write method signatures which are natural sounding.
The reason for the for or with in the method name is to identify the type or purpose of the first parameter to the method, which helps it read better.
Apple itself uses several conventions but that is the basic purpose, there is no concrete right or wrong just try to identify the first parameter of the method in the method name with either for or with.
And as for Apple conventions - get(whatever) is not even part of the actual conventions, so you could ask when do I use get or not.
Read this http://cocoadevcentral.com/articles/000082.php
also dont forget (by) NSURL urlByAppendingPathComponent etc - get a feel for it and you wont go wrong
You use "with" whenever the parameter is owned or to be owned, or will be a relatively permanent attribute by the object to the left of the "with" word.
initWithCapacity / arrayWithCapacity - the capacity will be an attribute of the container object being called and will be relatively permanent (until you add objects to it beyond the initial capacity)
viewWithTag – return a view "having" the specified "tag" attribute.
Whereas you use "for" to denote a looser association between the "desired" object and a "token" object that you use to get to it.
- objectForKey / attributeForValue – usually the "object" does not own the key.
- documentForWindow – the window is owned by the window controller and not the document. Furthermore there could be more than one window for each document.
But for looser associations of multiple
objects of the same type within a single method call, it's customary that you use something like:
doSomethingForFoo:withThisOtherFoo:havingYetAnotherFoo:
So the order for such complex call is:
for
with
having
In Objective-C i saw that we can use dot operator to set and get a value and for the same task i saw something like "[ob method]" inside square braces method call, what do we call for this kind of syntax?
Bracket notation: A staple of the small talk language, and now a lovely visage of the ObjC language.
Brackets were SmallTalk's way of saying "You there, take this message and do something with it", and so that's how they were implemented in Objective C. We send a message to the first part [Object] and state the message in the second part [Object Message];
Of course, they also serve a similar function with properties. Properties in most languages are written in dot notation (Object.property), but with Objective-C and the modern runtime's support for non-ivar-backed properties, and the #synthesize directive, properties automatically generate getters named the same. Sounds complicated? It isn't. If I have the property example, then I can access it in one of two ways:
self.example;
Or
[self example];
Easy!
But the #synthesize directive doesn't stop there. We get a getter, and a setter as well. The setter can be accessed the same number of ways as a getter.
self.example = foo;
is the equivalent of
[self setExample:foo];
Bracket notation is in fact so important, that the compiler optimizes most dot notation out to bracket notation at compile time.
This is called messaging, or message sending, you are sending a message method to the object ob
Its similar to calling a method in java or C++
So the equivalent in java would be
ob.method();
[ob method]
It's the way you call methods in objective-c. The same way you would call myObject.method(), in Java por example.
ob.myProperty
Is how you access ivars by using it's getter/setter method, for example:
Get method -> NSLog(#"%#",ob.myProperty);
Set method -> ob.myProperty = #"Hello World";
Notice that you also use the set method like this:
[ob setMyProperty:#"Hello World"];
Or use the get method like this:
NSLog(#"%#",[ob myProperty]);
In objective-c you normally will not create manually the setter and getter, because you have the opportunity to create them using #property and #synthesize.
This is known as function calling..
like you call function in other programing language like in java or c#:
ob.method() // where ob is object and method is the function name..
similarly if you want to call a function in objective c the syntax is calling function is like this :
[ob method];
I saw someone passing arguments by a button's tag as follow.
how could this work? and is it safe to do like this ?
NSCustomClass* cls = [[NSCustomClass alloc] init:#"",#"",#""];
[button setTag:(int) cls];
- (void)OnClick:(id)sender
{
NSCustomClass* cls = (NSCustomClass*)[sender tag];
// to do something with the "cls".
[cls release];
}
In fact,I didn't get weird results.
It works fine by passing arguments like 'NSString','NSArray' in this way.
Can you tell me why it is a bad idea?
Casting a custom class to an int is a very bad idea and you'll get weird results.
The tag is an integer property on all UI elements. It is declared as such on UIView:
#property(nonatomic) NSInteger tag;
You can assign any integer value to it, including any predefined constants:
#define Button1Constant 1
#define PushButtonConstant 2
// …Code
[button setTag:PushButtonConstant];
// …More code
if (sender.tag == PushButtonContent)
// Handle
In general you never want to abuse the frameworks. The tag is intended to store an integer and is used mainly to access a view with viewWithTag:, which can be useful in some cases if your view was built in Interface Builder but a referencing IBOutlet is inappropriate. Stuffing a pointer into an int can give unpredictable results, as others have indicated.
On top of that there's a memory management issue. Even if the pointer survives the cast you aren't retaining the object being pointed to. This in effect is a weak pointer but without any management by the run-time. Attempts to use the pointer will likely lead to the dreaded EXC_BAD_ACCESS. And who knows what ARC might do with this mess - blow up, I would expect.
To attach data to a button (which in and of itself sounds like a possible design flaw) you should either subclass or leverage the power of the run-time with objc_setAssociatedObject() and friends.
In general, casting from a pointer type to an integer type usually indicates a design flaw; there are very few legitimate reasons to do this, and I would strongly discourage doing it, especially in this case. It may work, but it's not guaranteed to work, simply because the tag property is not documented to be used this way. The more “hacks” that you put in your code, the harder it is to maintain.
Don't learn from the code where you saw this, instead stick to reputable tutorials and books.
As a side note, it is conventional in Objective-C to name all methods starting with a lowercase letter, so the method should be onClick: and not OnClick:. The exception to this rule is when the method starts with an acronym, for example -[NSString UTF8String].
You could subclass from UIButton and define a property by yourself, instead of using its tag property.
This question already has answers here:
When should I use the “self” keyword?
(6 answers)
Closed 9 years ago.
I have an attendant question to iPhone: Why do I need self.<> in viewDidUnload?
Since there is a difference between using self.instance and instance, when is only instance actually used? Just setting the reference to nil seems quite useless? Why is the option there?
Generally, you'll find a lot of useful information here: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html%23//apple_ref/doc/uid/TP40004447-SW4
For the rest of this answer, I'll assume that you are referring to properties automatically synthesised with the #synthesize directive in your .m files.
Executive summary
When you use the form self.property, retain/release is automatically taken care of for you. When you use the form instanceVariable without the self prefix, you're on your own with retain/release.
Longer explanation
When you omit the "self." part, what you really are doing is that you access the automatically generated underlying ivar which the compiler has given the same name as you have given to the property.
If you don't want the compiler to generate ivars of the same name, then you can use an extended form of the #synthesize directive, like this:
#synthesize myvariable=__myvariable;
That way, you will ask the compiler to create an underlying ivar called __myvariable instead of the default myvariable.
Using this extended form, you would refer to either self.myvariable (as a property) or __myvariable (as an instance variable), which can be handy to visually distinguish the two types of access.
With that in place, we can get to the substance of the matter.
When you use self.myvariable, you implicitly call the accessor methods (possibly synthesised for convenience), like this:
self.myvariable = #"Some string";
is equal to
[self setMyvariable: #"Some string"];
or, in the case of a right hand use of the property
myLocalVar = self.myvariable;
is equal to:
myLocalVar = [self myvariable];
The examples above use the accessor names recommended by Apple.
On the other hand, when you use the instance variable directly, you just assign the variables directly without going through the accessors.
Now, one huge advantage of using the accessors on the iPhone is that the automatically synthesised accessors also take care of the retain/release messages, so you don't have to worry about that - or waste code lines handling this somewhat tedious stuff.
Since there is no need to worry about retain/release when you are just reading a property, you could argue that you only need to use the property syntax (with self.) on the left side of an assignment, so whether you want to use the self.-syntax on the right hand side of an assignment is partly a matter of style.
Personally, I have developed a style where I try not to refer to automatically synthesised ivars, unless I have specified them in the #synthesize directive. Otherwise Apple might one day change the way an unspecified #synthesize directive works, and my builds would break. But that is just a personal precaution of mine.
There is one exception to all this, as stated in the docs linked at the top of this answer - and that is that you should not use accessors to the class' own instance variables in the init* methods. One the Mac, you shouldn't use them in the dealloc methods, either, but this is one point where Apple's coding recommendations differ between the two platforms.
Ok, this was a long answer to just say, read the docs, but I hope it clarifies things a little. Memory management in reference counted environments is not trivial, so don't despair if it isn't clear at first.
PS: And if you think this the sort of worries that others should solve for you, log a bug with Apple to ask for garbage collection on iOS. It works nicely on 64-bit OS X.
I'm a little bit confused now after I've seen a code snippet for iPhone SDK which makes use of -> rather than dot notation. It looks a lot like PHP but it does work on the iPhone. Can someone explain what's up with ->, is that some deep C-secret I should know about?
Example:
- (void)setFileURLs: (NSArray*)elements {
if (self->fileURLs != elements)
fileURLs is an instance variable or property, like so:
#property(nonatomic, retain) NSArray *fileURLs;
and there's an #synthesize for fileURLs.
Now what I think this is: Because this is the setter method for fileURLs, it would be bad to use dot notation to access the instance variable. In fact, when I do it, the application crashes. That is because it calls itself over and over again, since the dot notation accesses the accessor method and not the ivar directly. But -> will access the ivar directly.
If that's right, the question changes a little bit: Why then write "self->fileURLs" and not just "fileURLs"? What's the point of adding that self-> overhead in front of it? Does it make sense? Why?
a->b is just another way for writing (*a).b. This is a way for accessing fields of a structure or instance variables of an object that are referenced by a pointer.
See section "Other operators" at:
http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
Since self is a pointer, you have to use -> and not . to access its members. Prepending the self reference to fileURLs is probably just a coding style used by the author (equivalent to writing this.member).