Objective-C tab settings and whitespace style - objective-c

Apple's Objective-C documentation, references, and generated code seem to be totally inconsistent with their coding style. I can not determine the "preferred" style (if one exists) for Objective-C and Cocoa source code.
Here's what I've ran into so far.
Tab settings
Xcode's default setting is set to tabs. However, generated projects are always created with 4 spaces regardless of your tab settings. Worse, some generated code has stray tabs hanging around. Downloaded code examples seem to vary from project to project as well.
Method definition spacing
In Apple's example code, different styles of method definition even vary within a single file. But the most common style of spacing seems to include a space between the - or + and spaces only between addition arguments. This style is also used in the Xcode reference library which leads me to believe it is the preferred style.
- (IBAction)reloadData:(id)sender;
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
Inconsistent variates:
- (IBAction) reloadData:(id)sender;
- (IBAction)reloadData:(id) sender;
-(IBAction)reloadData:(id)sender;
- (IBAction) reloadData: (id)sender;
- (id)tableView: (NSTableView *)aTableView objectValueForTableColumn: (NSTableColumn *)aTableColumn row: (NSInteger)rowIndex
Brace style
Another thing that is widely inconsistent is the brace style. There are two popular styles:
Open brace on its own line:
#interface Foo : NSObject
{
}
- (id)init
{
}
Open brace on the same line as the method declaration:
#interface Foo : NSObject {
}
- (id)init {
}
Question
Is there a recommended coding style for Objective-C by Apple? If not, what style do you prefer and why?

I found that I was constantly setting the generated projects to my own preferred style, so I edited the template files to my preferences (tabs for indent, braces on a line of their own). The files are here:
/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Project Templates/
I select everything, get rid of all indentation with cmd-[ (as many times as the document needs) and do Edit->Format->re-indent. I have this hooked up to shift-cmd-[ for convenience.
I've seen the differences in style for example code and project templates and just assumed it was due to the age of the files being different. I guess they have had different internal coding style guides which have changed.
Here's the Google Obj-C style guide:
http://google-styleguide.googlecode.com/svn/trunk/objcguide.xml
and another nice one from CocoaDevCentral:
http://www.cocoadevcentral.com/articles/000082.php
of if you really want to follow Apple rules, the Objective C programming guide has a bunch of code examples to take rules from.
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/

Related

Proper naming convention for a delegate method with no arguments except the delegating object?

I have a class called ABCCalendarView. It requires an NSCalendar, and gets this object from its delegate. I'm trying to work out what to call this delegate method, and I want to fit in with the best practices of the Cocoa framework.
According to the 'Naming Methods' section of Apple's 'Coding Guidelines for Cocoa', I should:
Start the name by identifying the class of the object that’s sending the message:
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
The class name omits the prefix and the first letter is in lowercase.
A colon is affixed to the class name (the argument is a reference to the delegating object) unless the method has only one argument, the sender.
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;
This would suggest I should call the method:
- (NSCalendar *)calendarViewUsesCalendar:(ABCCalendarView *)calendarView;
However, looking at actual examples of this situation in the Cocoa framework, I can see that the actual convention used seems to prefer putting the class name at the end of the method name in this case. For example:
// UITableViewDataSource has the method:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
// UITableViewDelegate has:
- (NSIndexPath *)indexPathForPreferredFocusedViewInTableView:(UITableView *)tableView
// UIScrollView has:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
If I follow this convention that would suggest I should call my method:
- (NSCalendar *)calendarForCalendarView:(ABCCalendarView *)calendarView;
Why is there seemingly a discrepancy between Apple's guidelines and what they've actually done? And what convention should one follow when creating a delegate method which is basically just setting a property of the calling object?
I think that rules document is slightly internally inconsistent. There are two "General Rules" which state:
If the method returns an attribute of the receiver, name the method
after the attribute.
and
Make the word before the argument describe the argument.
These, along with the precedent in the SDK's names, both argue for your second formulation:
- (NSCalendar *)calendarForCalendarView:(ABCCalendarView *)calendarView;
I think there's ample evidence in the SDK names that the rule you found in the delegate section should be restated. As you point out, it says
Start the name by identifying the class of the object that’s sending the message
but it should say, in my opinion: "Send an instance of the caller as the first parameter". Which is sort of half naming rule, half design pattern. With that, those single parameter, attribute returning delegate names can be of the form returnTypeSenderType: (which is how they are in practice) without running afoul of the other parts of the doc.

Why cant I see all available methods or properties present in a Class in XCode?

I am noob to XCode and Obj-C world, so pardon me for my naive question.
Following a tutorial, I was writing a basic program in Cocos2D that would accept touch input.
And one of the task was to add implement ccTouchBegan method, but that would not show up in XCode's code sense.
I wanted to implement this method
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
but I would find only this one (related to touch began)
-(BOOL) ccTouchesBeganWithEvent:(*)event
Now that I a noob, how do I explore list of all available methods and properties for a particular Class?
The image shows list of available methods that starts with ccT. ccTouchBegan and ccTouchEnded showed up because I have implemented them already. Else, they would not show just like ccTouchCancelled and ccTouchMoved events didn't show up.
How do I see all available methods & properties of a Class or Object?
To see all the available methods & properties just press Ctrl+Space
Option+Click on the object (in this case, that would be the delegate name in the header file between the < >). A small help popup will appear. Click the blue text inside the popup and the Organizer window will open at the documentation for the Class. The Documentation has all methods and properties you can use.
Just press Backspace 3 times to delete the ccT you typed in. The list will increase with every character you erase. The full list not only shows methods, as you will see.
Maybe it does not show up because you have already defined it in your code? That would be logical, as double implementation would lead to a compiler error.

iOS Localizable.strings file for XIB files?

I'm translating an iOS project into Portuguese and I've created a pt.lproj/Localizable.strings file, and I've added NSLocalizedString() into the source code. It all works! With one slight problem - the strings within XIB files don't get translated... I know this is by design though.
I've seen that the ibtool command can be used to rip strings from an XIB file called x and put it into a file called x.strings... but my question is, is there a way to pull the strings from ALL the xib files and put them all into one .strings file (e.g. Localizable.strings? or even another one called XIBs.strings would be fine?)
You have two options how to translate xib files. One is you connect the UI elements to outlets and set your strings in your viewDidLoad method using the NSLocalizedString macros.
The second option is to provide a separate xib for each language your app supports. You don't have to create them manually, you can use the ibtool command (i assume your source language is English and target is Portugese):
ibtool --strings-file pt.lproj/Example.strings en.lproj/Example.xib –write pt.lproj/Example.xib
To collect strings found in your project you can use genstrings command - however i recommend using this python script to collect all your strings - it can nicely handle the situation when you need to add/remove strings to your app without having to translate and/or manually merge all previous strings
Edit
Oh and i found the article that i learned this trick from
I made a category to do this:
#implementation UIView (Localise)
- (void)localise
{
[self.subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
[view localise];
if ([view isKindOfClass:[UILabel class]]) {
UILabel *label = (UILabel *)view;
[label setText:NSLocalizedString(label.text, nil)];
}
}];
}
Then in your views:
- (void)awakeFromNib
{
[super awakeFromNib];
[self localise];
}
You'll need to add support for other UI elements (textField.placeholder = NSLocal...blah blah), but that'll do the trick for UILabel and children.
Probably not great performance-wise but does the job.
It's going to depend on the app and the number of localizations, but in general I prefer separate .xib files, because layout may change. Put the localized files in pt.lproj/.

XCode skeleton projects overriding

I'm pretty new to Objective-C, so I am not entirely sure of the terms I should be searching for. Apologies if you've seen this question before.
I have noticed that in the skeleton projects that XCode produces contain overrides like so:
- (void)viewDidLoad
{
[super viewDidLoad];
}
I am not sure why this is part of the code that is generated. I am confident that I could omit this method and not affect the application because it simply calls the method on the parent class. Is this method stub just here to show the developer that they can override this commonly overridden method, or is this something in Objective-C that I have not yet come across?
It's a method that you'll often want to override, so it's included in the template as a convenience. If you don't add any code of your own to it, you could as well remove it altogether because only calling super is the same as leaving it out.
I suspect it's also included to remind you that you have to call super if you override it.
Yes, if you have nothing to add to this method it could be left out. It is there to provide you a template where you can add your code for things you want done in viewDidLoad.

"'Objects' may not respond to 'functions'" warnings

for the last couple of weeks I've finally gotten into Obj-C from regular C and have started my first app. I've watched tutorials and read through a book along with a lot of webpages, but I know I've only just begun. Anyway, for most of the night and this morning, I've been trying to get this code to work, and now that it will compile, I have a few warnings. I've searched and found similar problems with solutions, but still no dice. What I'm trying to do is put an array made from a txt document into the popup list in a combo box.
AwesomeBoxList.h:
#import <Cocoa/Cocoa.h>
#interface AwesomeBoxList : NSObject
{
IBOutlet NSComboBox *ComboBoz;
}
-(NSArray *) getStringzFromTxtz;
- (void) awesomeBoxList;
#end
AwesomeBoxList.m:
#import "AwesomeBoxList.h"
#implementation AwesomeBoxList
-(NSArray *)getStringzFromTxtz
{
...
return combind;
}
- (void) awesomeBoxList
{
[ComboBoz setUsesDataSource:YES];
[ComboBoz setDataSource:
[ComboBoz getStringzFromTxtz]: //'NSComboBox' may not respond to 'getStringzFromTxtz'
[ComboBoz comboBox:(NSComboBox *)ComboBoz objectValueForItemAtIndex:
[ComboBoz numberOfItemsInComboBox:(NSComboBox *)ComboBoz]]];
/*'NSComboBox' may not respond to '-numberOfItemsInComboBox:'
'NSComboBox' may not respond to '-comboBox:objectValueForItemAtIndex:'
'NSComboBox' may not respond to '-setDataSource:'
*/
}
#end
So, with all of these errors and my still shallow knowledge of Obj-C, I must be making some sort of n00b mistake.
Thanks for the help.
There does seem to be a generally large amount of confusion here, mostly manifested in your last
(4) line(s) of code. You are aware that the ':' symbol is used to pass arguments to methods, not terminate a line? You are essentially daisy chaining those last 4 lines together in a way that makes no sense. As for the specific warnings, getStringzFromTxtz is a method you defined on AwesomeBoxList, not a method of NSComboBox. numberOfItemsInComboBox: and comboBox:objectValueForItemAtIndex: are NSComboBoxDataSource Protocol methods, intended to be implemented by your class on behalf of an NSComboBox, not NSComboBox methods. I would recommend doing a bit of reading on Delegates and Protocols.
To elaborate:
In order for your AwesomeBoxList class to use an NSComboBox, it needs to provide information to the combo box that the combo box needs to know. In the Apple Universe, situations like this are typically handled with the Delegate Design Pattern. Specifically, the combo box needs to know how many items it will be showing as well as the object representation for each of the shown items. The combo box declares the interface for doing this in the NSComboBoxDataSource Protocol. By providing this info, you are acting as the datasource for the combo box. You can tell the combo box that it should defer to your class for its data by setting yourself as its dataSource property in Interface Builder or with a call to
[ComboBoz setDataSource:self];
from somewhere in your AwesomeBoxList's implementation. That will ensure that the combo box calls methods in your class to populate itself with info. There are two methods specifically that your AwesomeBoxList class should implement, and which will be called by the combo box:
- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index {
switch (index) {
// Return some object that is represented by index in the combo box
}
}
- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox {
// return theNumberOfItemsInYourComboBox;
}
Providing a meaningful implementation is all you need to do to populate your combo box with data. I don't know the specifics of what you want here, but that is the pattern you want to follow. Hope that helps a bit more.
Well, the getStringzFromTxtz won't work being sent to an NSComboBox instance as that method is declared and defined in your AwesomeBoxList class. This method will not be found at runtime.
Also, I think you may need to get your head around delegates and data sources - the other methods are part of the NSComboBoxDataSource protocol. Check out the Combo Box Programming Guide in the docs for examples.
Those methods do not exist. See the NSComboBox documentation for more information.
Instead of:
[ComboBoz
comboBox:(NSComboBox *)ComboBoz
objectValueForItemAtIndex:[ComboBoz numberOfItemsInComboBox:(NSComboBox *)ComboBoz]];
Try:
[[comboBox objectValues] objectAtIndex:[comboBox numberOfItems] - 1];
Also, note that the platform convention is to use a lower-case letter at the beginning of an ivar.