Here's a quicky question. Which method name makes the most sense for an Objective-C Cocoa application?
-(void) doSomethingWithAnimation:(BOOL)animated
or:
-(void) doSomething:(BOOL)animated
or even:
-(void) doSomethingAnimated:(BOOL)animated
I think the Cocoa convention would give your examples the following semmantics (ignoring the BOOL type for the argument, obviously):
-(void) doSomethingWithAnimation:(BOOL)animated
would actually expect an Animation as the parameter (i.e. something that represents the animation.
-(void) doSomething:(BOOL)animated
would expect the Something to do.
-(void) doSomethingAnimated:(BOOL)animated
would, as Noah answered, do something with optional animation.
-(void)doSomethingAnimated:(BOOL)animated seems most consistent with Apple's naming style. For reference, check the iPhone UIKit docs - UINavigationController's -popToRootViewControllerAnimated: method, for instance.
Here's another option to consider: make two methods, -doSomething and -doSomethingWithAnimation.
Then, if you want, you can have them both tail-call a third, private method, and give that method any name you want. :)
write your comment clearly and tersely for example :
//do Something with the Animation
Then write your method name based on this comment, like below
doSomethingwithAnimation:(BOOL)animated
Objective-C and Cocoa are designed to read well, so if your method cannot be a clear narrative of your code, it might not be well named.
Related
When adding a custom initializer to a subclass, are there any rules as to what kind of parameters it should take? As an example, is there a particular reason why UIView doesn't have the initializer below, and would there be any argument for not adding it to a custom subclass of UIView?
- (instancetype)initWithFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor;
I haven't been able to find an answer to this on the web, so I hope that some of you can enlighten me.
You can add anything in there. But then you can add so many that it becomes ridiculous...
initWithFrame:backgroundColor:tintColor:alpha:hidden:userTouchEnabled:...
It really depends on what you're using the subclass for.
For instance, you might create a PlayingCardView subclass. This is going to have certain properties... suit, faceValue. Because every card MUST have a suit and face value it makes sense to put these into the init method.
So it would be sensible to create an initialiser...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue;
because every card has to have a suit and a face value.
Equally, you could have another property backImage to set the image on the "back" of the card. So you could have...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue backImage:(UIImage *)backImage;
Now you can use one of two initialisers. One for the "default" back image the other to set a custom back image.
Then you get into designated initialisers in this case, it would be preferable not to have repeated code in both init methods so you would make the first method like this...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue
{
UIImage *defaultBackImage = [UIImage imageNamed:#"defaultCardImage"];
return [self initWithSuit:suit faceValue:faceValue backImage:defaultBackImage];
}
And the designated initialiser would do all the actual setting up of the card.
In reality though, there is no fixed way and no correct way of doing this and it can take a while to find a pattern that you find easiest/best to use.
Your custom initializer can take any parameter you want to. As any other class, UIView define some let's say basic behaviour, so if you need any other behaviour you are free to add it using a subclass for example. Don't complain that UIView or any other classes don't have methods that you think would be good for them to have.
I would recomend you not write a custom initializer which has many arguments because it increase the complexity. Think exactly what is needed for that classes to be initalized correctly.
This is something I have been curious about:
If you create a new UIViewController subclass in Xcode, they stub in a few functions including ViewDidUnload. But there is no dealloc method.
Why wouldn't they stub that method into the class?
You can create your own templates for Xcode. If you want to add a dealloc method to your template, go for it.
Look in ~/Library/Application Support/Apple/Developer Tools/Templates/.
I think that's a reasonable question - it would seem including it would make sense, given there's a high liklihood that it would be used. But I suppose the only answer which is possible here, is that they decided not to (for whatever reason). You can of course add it yourself - and in iOS5 it may be fairly redundant with ARC.
In the function viewDidUnload it is initially empty. However, I'm following a tutorial where at the end of the function they write [super viewDidUnload]. I noticed that in the dealloc function, [super dealloc] is automatically written at the end. Why isn't it automatically written at the end of viewDidUnload? Does it make a difference? What does it do?
Also, is this a Cocoa question, or an Objective-C question?
This link may help: iPhone: [super viewDidUnload] calling order
Basically, if the superclass is just UIViewController, [UIViewController viewDidUnload] does nothing, so that's why it's not automatically added.
Call it at the end of the function.
I've had a lot of miscellaneous errors when i called at the beginning. I found a lot of places on the web discuss the topic, some say beginning, some say at the end. Before i researched, i figured it should be called at the end due to similar patterns of the structure and nature of the language (such as how touch events are handled).
My logic suggests that if i'm going to call the super, or parent of an object in question, i have to also think that the parent or super wouldn't know of the existence of the child object in its default implementation, and who knows what it might do. So when over-riding this method it would be logical to think that when setting outlets and properties to nil, that the super's unload method might do something like unload the view in a view controller while those outlets still exist.
Due to all the questions and answers i found, there is no clear cut solution. Apple doesn't give the immediate answer, but they provide an understanding of how the loading and unloading of views occurs. I quit looking for examples on this one and i'm sticking to the logic behind the call to super at the end of this function.
What i wouldn't do is assume I can guess what code is being run in private API's and that anyone other than an apple doc or an apple developer will have the right answer. nevertheless, this is my suggestion based on what i've experienced, perhaps the correct answer is that it should be either/or depending on what your doing in the method. Open to more suggestions.
I'm working through an iPhone development book* without really knowing Objective C. For the most part I'm able to follow what's going on, but there are a few method declarations like the one below that I'm having a bit of trouble parsing. For example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return [self.controllers count]; //controllers is an instance variable of type NSArray in this class
}
It looks this is a method called numberOfRowsInSection, and it returns an NSInteger, and takes an NSInteger as a parameter which is locally called 'section'. But I don't understand all the references to tableView, or why this takes a parameter when it is not used within the method. Can somebody clarify this? Thanks.
*p. 258, Beginning iPhone 3 Development, by Mark and LaMarche, published by Apress
Update: I was able to find another SO thread that goes into a bit more detail: Method Syntax in Objective C
This is a method called:
tableView:numberOfRowsInSection:
It takes two parameters:
a UITableView*
a NSInteger
The method also takes an implicit self parameter , which is the instance it is called with. As dreamlax notes, it also takes an implicit _cmd, which is the method that currently gets invoked.
As Mark says, it is completely common to not use certain parameters if you are conforming to a certain interface.
This is a method called tableView:rowsInSection: that UITableView specifies for its delegates. The tableView argument is there in case you have one controller in charge of several UITableViews, so that it can tell which one is talking to it. It's also useful if you need to query the UITableView for information in order to decide what you want to do. This is very common in delegate methods.
This method is conforming to the UITableViewDataSource protocol. If you're familiar with C# or Java, a protocol is like an interface.
It's completely legal and not too abnormal for a method conforming to an interface or protocol to ignore some of the arguments.
The question is not only regarding the headline, but more of a "how will I achieve this, without trying to force a Java/Flash design into an Objective C (iPhone)program".
I have 6 views that extends UIView, these views all have different behavior but share certain methods, like -(void) update and -(void) changeState:(NSInteger)state.
A viewController, whose job is it to update, instantiate and display these views has a switch block to do this. So switch(4) {...} instantiates UIView4, but as I need a reference to the currently instantiated view (to do update and changeState:), I have a UIView property on my ViewController called self.currentView. As the instantiated UIView4 extends UIView I can easily go [self.currentView addSubview:UIView4instance] and then release the UIView4instance.
Now how will I call the [UIView4instance update] method on the view? or the [UIView5instance changeState] etc. etc.
Since I added it to self.currentView which is of type UIView it no longer has any reason to believe it has an update or changeState: method, meaning I cannot iterate the views and send them these messages.
This approach brings on a ton of other problems, I would need to test and typeCast my views each time I needed to do any operations on them.
If I were doing something like this Composite Pattern approach in, say, Java. I would either write an interface that all the views (UIView1, UIview2.... UIViewN) would implement. Or maybe an abstract class that all the views inherited the changeState: and update methods from.
This way I could have self.currentView just know that I'm adding objects to your view and they all conform to these methods.
The two solutions I can think of, with my very small Objective-C experience is:
doing it with delegation or categories, but this seems overkill in every way :/
I guess I could also extend UIView and then extend my class extending UIView again, but there is probably a reason Objective-C does not directly support abstract classes...
Hope someone could point me in the right direction regarding these issues.
Thanks:)
Yes it is equal. You can declare a protocol
#protocol MyViewProtocol
-(void)update;
-(void)changeState:(NSInteger)state;
#end
and declare your subclasses like
#interface MyUIView3 : UIView<MyViewProtocol> {
....
}
....
#end
Then, the declaration
UIView<MyViewProtocol>* view=[[MyUIView3 alloc] init];
means that view is an instance (of a subclass of) UIView which also conforms to MyViewProtocol.
Just the way it works in Java, I think. See the apple doc on protocols.
One thing to be aware of is that while defining a protocol like this is a convenience and certainly makes things clearer, it is by no means necessary to make your solution work. Objective-C binds methods at runtime, and so all you really need to do is to make sure all your view classes implement the methods you care about and call them.
You will get a complier warning for this, but it will work.
Now, in general it's probably preferable to define a protocol like this and it's what I generally do. But it's also important to remember that runtime binding is there and can be incredibly powerful.