Total newbie question follows...
I am learning Objective C based Cocoa (OS X) app development. Most of the books and videos I have are iOS based, so I'm seeing how the two platforms differ.
I have converted a simple iOS app to OS X. I got the converted OS X app to work fine, but I have a question: Why doesn't OS X ViewController.m file have an #interface section?
I created the iOS app using Interface Builder, dragging UI elements from Main.Storyboard to ViewController.m, in the assistant editor. I dragged a UILabel cell into the #interface section of ViewController.m, created an instance variable #property. In iOS, the ViewController.h public #interface section remains empty.
In the OS X app, I dragged an NSTextField cell to the #interface section of the ViewController.h file to create a similar instance variable.
Is the OS X ViewController.h #interface section the correct place for IBOutlets? Doesn't this expose these instance variables to other classes? In the iOS case, since the instance variables were NOT added to the ViewController.h file, I assume they are hidden, correct? Can I make the OS X instance variables private?
As I mentioned, the OS X code works, I'm just trying to understand the differences between the platforms, and make sure I am headed in the right direction.
Before I answered I wanted to check if the same happened to me-- but when I created a custom NSViewController in a new iOS OR OS X app, both would generate the #interface in the implementation file (.m file)
So I'm not sure why you are seeing that.
However, to answer your question, (as you said) properties declared in the #interface in your header file (.h) are public. While properties declared in the #interface in the implementation are private. This is because the #interface inside of your implementation is called an "Extension". Which is basically just an anonymous "Category".
Unless outside objects need a reference to your outlets, then I would continue placing them inside of your implementation file. If for whatever reason one isn't generated for you, there is nothing wrong with manually typing out your own class extension to declare the properties
Yes you are right instance variable should not added to ViewController.h file to make them private. Same like you can make instance variables as private variables in OS X . Like this`#interface MasterViewController ()
#property (nonatomic, weak) NSString* strTemp;
#end
#implementation MasterViewController
You can get difference between cocoa and cocoa touch by already posted question for this
Related
Some background: I'm making a Obj-C project for some numerical analysis, and want to add a graph. I found core-plot, and had no problem adding the framework and QuartzCore frameworks to my project.
My question now is how to actually utilise it - I have a project with an interface through Interface Builder (MainMenu.xib), an AppDelegate and another class used for modelling the mathematics. I have searched the internet and can only find tutorials for its use within iOS, which isn't what I'm doing - and I don't understand how to convert that to OSX.
I had assumed that I would add a custom view to the MainMenu.xib and link that to a new property using someting along the lines of
#property (assign) IBOutlet NSView *graph;
Although now that I look at it, putting a NSView object inside a NSObject interface seems silly.
Thanks in advance for your help!
Update 1: So I changed my code to
#property (assign) IBOutlet CPTGraphHostingView *graph;
And changed the property of the custom view to the same, CPTGraphHostingView. The two are now linked, and I have an outlet called "graph" to play with. The challenge is now putting a graph into that space.
Thanks again!
I'm currently taking the Stanford CS193p iPhone and iPad application development course ( http://itunes.apple.com/itunes-u/ipad-iphone-application-development/id473757255 ) and in the second lecture I got stumped when he connected the buttons of the calculator to the .m file, he connected the display label (that shows the value on the calculator) to the .h file...
My understanding of the whole implementation and header file thing was that you declare the class members in header and say what they do in the implementation, which is why this doesn't make sense to me...
any help would be greatly appreciated
It is possible in Objective-C for a .m file to contain methods for a class that the .h file for the class doesn't declare. In fact with the Categories feature of the language there can be more than one .h and .m that define all the methods for a class.
As far as what can be connected, the keyword IBOutlet marks properties or variables and IBAction marks action methods. These are just hints for the editor; all of the "connections" are set up at runtime automatically.
I noticed two things when switching between iOS and regular OS X development:
//SomeClass.h
#interface SomeClass: SomeUIClass
#property (retain)SomeProperty* someProperty;
#end
//SomeClass.m
#interface SomeClass ()
{
SomePrivateVar* somePrivateVar;
}
#end
#implementation SomeClass
#synthesize someProperty;
#end
The above will compile just fine under iOS. That is:
I can synthesize the property without declaring an ivar explicitly
in the public #interface
I can further declare other private ivars in the .m file under the
anonymous category (class extension).
However, if compiling for OS X and subclassing some NS-based class as opposed to a UI-based one (say, NSView instead of UIView), both the above things result in compiler errors.
I guess I thought Objective-C 2. allowed for the above in general, but they are only "shortcuts" in iOS? or what's the deal with them being allowed in iOS but not in OS X?
Those are features of the "modern runtime" which can only be used for 64 bit apps on Mac OS X. You're probably building a universal binary that also includes a 32 bit version.
I'm trying to learn some of the basics of developing OS X apps with XCode and Objective-C, but I am already running into problems.
I have a project I made from a while back which worked very well for me, however, when I try to replicate the results I had last time, I run into numerous errors.
I have two files, a .c and a .h named "AppDelegate"
in AppDelegate.h:
#import <Cocoa/Cocoa.h>
#import <WebKit/WebView.h>
#interface AppDelegate : NSObject {
IBOutlet WebView *gameFrame;
}
#end
then, in AppDelegate.c:
#import "AppDelegate.h"
#implementation AppDelegate
-(void)awakeFromNib
{
}
#end
In IB, there is an NSObject named 'AppDelegate' and its class is 'AppDelegate'.
However, when I try to run this, I get 11734 errors...
When I click on the error icon at the bottom of the XCode window, it lists a bunch of code that seems to be involving NSStrings, but I cant make any sense of it...
Also, within my code, the
#end
line in both the .c and the .h are highlighted with an error saying:
'Expected identifier or '(' before '#' token.'
I don't understand what XCode is tripping up on when it tries to compile, I don't see any logical place for a '(' to go and I don't think I left anything unidentified.
Any help would be appreciated.
That's because that isn't valid C code.
You named your module file AppDelegate.c, which indicates that it contains source code written in (more or less) pure C. But it does not: You wrote a class interface and implementation in Objective-C, which is a superset of C (all C is valid Objective-C, but not all Objective-C is valid C—in particular, classes aren't).
For this, you must name the module file AppDelegate.m (or anything else, as long as it ends with .m; naming it after the class is a convention worth following). The .m suffix indicates a module (usually containing a class implementation) written in Objective-C.
So, just rename your module file from AppDelegate.c to AppDelegate.m. Make sure you do this in Xcode, not the Finder: If you do it in the Finder, Xcode will only care that there is no longer a file named AppDelegate.c; it won't notice the rename.
For your convenience in creating future classes, Xcode provides a template in the “New File” panel for creating subclasses of certain Cocoa classes; your AppDelegate should be a subclass of NSObject, and templates are also provided for NSView, NSDocument, UIView, UIViewController, and a few others. The files created by the template will already have the correct extensions.
This is a style question:
Because Apple reserves the "_" privatization for its keywords, I was thinking of something along the lines of the following:
#import <Cocoa/Cocoa.h>
#define _(name) pvt_##name
#interface SFMeasureViewController : NSViewController {
#private
NSTextField *_(label);
}
#property (retain) IBOutlet NSTextField *label;
#end
#implementation SFMeasureViewController
#synthesize label = _(label);
#end
This is to help force the difference between [self label] and using label when it comes to retaining, and disposing of the variable properly. Here, using the term "label" within the code returns an error, forcing the user to distinguish between a call to self.label or _(label).
Now _(label) contains 2 more characters (shift-characters at that) than _label does. Is there any other good conventions out there? vLabel? Nothing is as quite as clear as _label but since its reserved, I don't want to use it.
Thoughts, critiques? This is for a style guideline at work, for primarily C++ work using Objective-C++ when necessary.
Thanks,
Well, Apple recommends not to use _ as the first letter of anything, especially on method names. But as for instance variables, they themselves go against this principle in their sample codes. So I think _... is perfectly fine for that, without making the macro. I like the property names var vs. the backing instance variable theVar, too. More about this, see the discussion here in SO.
In the new runtime (i.e. 64 bit on Mac, or iPhone OS, or iPhone simulator starting the ones coming with XCode 4) you don't even have to declare a backing instance variable explicitly; an ivar is created by the compiler when you #synthesize it, and you can't access that ivar directly. Thus, if you are OK with supporting only those platforms, that's the best approach.
Actually, it is not hard to distinguish label/self.label inside of module, so I doesn't see any problem in using the same name for property and field.