Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Feb 11, 2013, 05:27 PM   #1
xShane
macrumors 6502a
 
xShane's Avatar
 
Join Date: Nov 2012
Location: United States
Basic Objective-C Questions

Hello,

I'd currently classify myself as a beginner with regards to Objective-C programming on the Mac. I've done some Java but it's been awhile. I've just finished reading a book oriented towards beginners of Objective-C in order to obtain a simple grasp of the language. I've also done a few Xcode Objective-C based tutorials on the internet.

I had an idea for an application that I could possibly benefit from via using, and it's also a very simple (or so it seems) idea. Nothing too advanced. I've been developing it for a few days now and it's been a great learner's experience so far (I prefer to get my feet wet).

As I've been working on this simple app, I've had a few questions arise. Right now I'm doing all my code through the provided AppDelegate header and implementation files. I'm assuming this is acceptable for basic applications with not too many needs. However, as it get more "advanced" (I have lots of different category features planned), should I look into tying my interface-based app to other files, for better organization? Can I still connect outlets and actions to these other non-Delegate files, too?

Also, I'm assuming that I should never access variables declared in header files directly, and that I should use the appropriate getter and setters provided from @synthesize? For example, I enter text in a field, and click a button. I then assign the string in the text field to a variable. I should use a setter instead of directly setting (i.e. variable = string), correct?

This brings me to one last question. I noticed when designing my user interface I have two possibilities when "linking" objects to code: Outlets and Actions. I define and use outlets when I want to access/use/set that object via code (i.e. setting a text field within my code by calling _object setString:string;, etc). _object has to be an outlet to do this. I use an action when I want to connect a method/function to the object. Am I doing this correctly? My app has a lot of text fields to be set and I notice after awhile I have a ton of outlets "spamming" my header file. For now I organize my outlets into categories/windows using comments.

Thanks for being patient.
__________________
Macbook Pro 15" 2.6, 8GB, 750GB, 1GB VRAM
24" Asus display


"Be the change that you wish to see in the world."

Last edited by xShane; Feb 11, 2013 at 05:37 PM.
xShane is offline   0 Reply With Quote
Old Feb 11, 2013, 06:51 PM   #2
mfram
macrumors 6502a
 
Join Date: Jan 2010
Location: San Diego, CA USA
I generally create a new subclass of NSObject as my application's main "controller" logic. Keep the logic out of the app delegate and only use the pre-created app delegate for setting things that are specifically needed in that delegate. Then I use Interface Builder to create an instance of the controller object. Once that is done, you can connect UI elements up to your controller as needed. This is for basic apps. If you end up having multiple windows or pop-ups, then you can create more controllers to go along with them.

If you need special data model objects, you can create more classes to deal with them as necessary.

Remember, you connect outlets and/or actions to instances of objects. Not classes. IB can create instances of classes if it makes sense to do so.
mfram is offline   0 Reply With Quote
Old Feb 12, 2013, 02:50 PM   #3
xShane
Thread Starter
macrumors 6502a
 
xShane's Avatar
 
Join Date: Nov 2012
Location: United States
Quote:
Originally Posted by mfram View Post
I generally create a new subclass of NSObject as my application's main "controller" logic. Keep the logic out of the app delegate and only use the pre-created app delegate for setting things that are specifically needed in that delegate. Then I use Interface Builder to create an instance of the controller object. Once that is done, you can connect UI elements up to your controller as needed. This is for basic apps. If you end up having multiple windows or pop-ups, then you can create more controllers to go along with them.

If you need special data model objects, you can create more classes to deal with them as necessary.

Remember, you connect outlets and/or actions to instances of objects. Not classes. IB can create instances of classes if it makes sense to do so.
Thanks for your input. I understand what you're saying.

I did some further research on Application Delegates and Objective-C/Cocoa interface-based applications and see that the App Delegate should only be used for application-level stuff. I think what I'll do (for now) is have a separate file for all outlets/actions which then call methods from a set of "core" logic files. I now have to change the controller(s) and migrate/fix some code, but I'm learning so much

EDIT: So you're saying a new view controller per Window/pop-up? Do you also create new '.xib's per view controller? I'm still a bit new to file organization.
__________________
Macbook Pro 15" 2.6, 8GB, 750GB, 1GB VRAM
24" Asus display


"Be the change that you wish to see in the world."

Last edited by xShane; Feb 12, 2013 at 04:32 PM.
xShane is offline   0 Reply With Quote
Old Feb 12, 2013, 07:19 PM   #4
mfram
macrumors 6502a
 
Join Date: Jan 2010
Location: San Diego, CA USA
Of course, the answer is always "it depends". For something like a modal dialog box, there are already Cocoa routines to create those and return the user response. So you wouldn't need a separate controller for that. Standard dialogs (open file, print, etc.) already have standard Cocoa calls.

For non-modal, do whatever makes sense. I once wrote an app that would allow the user to bring up multiple little stopwatch windows. In that case, the user could start several of them. So I put the window and controller for the stopwatch in a separate xib. Each user request to start a new stopwatch instantiated a new window/controller pair from that "stopwatch" xib.

But if you have an optional extra window where it's showing or not showing (like, say, a high score window) then you could just add it to your existing xib.

Different problems call for different solutions.
mfram is offline   0 Reply With Quote
Old Feb 18, 2013, 10:26 AM   #5
mduser63
macrumors 68040
 
mduser63's Avatar
 
Join Date: Nov 2004
Location: Salt Lake City, UT
Send a message via AIM to mduser63
Quote:
Originally Posted by xShane View Post
Also, I'm assuming that I should never access variables declared in header files directly, and that I should use the appropriate getter and setters provided from @synthesize? For example, I enter text in a field, and click a button. I then assign the string in the text field to a variable. I should use a setter instead of directly setting (i.e. variable = string), correct?
There are some who don't do this and will disagree with me, but you should always use the appropriate getter and setters instead of accessing instance variables directly. The only exception to this is inside the implementation of a custom setter/getter (where you have to do direct ivar access of course), and inside initialization (init) methods. Apple's document on encapsulation in Objective-C explains all this (and more).
__________________
27" 2.93 GHz Core i7 iMac, 12 GB RAM
2.3 GHz Retina MacBook Pro
12" 1.33 GHz Superdrive PowerBook G4, 1.25 GB RAM
iPhone 5, iPad 3, etc.
mduser63 is offline   0 Reply With Quote
Old Feb 18, 2013, 12:52 PM   #6
xShane
Thread Starter
macrumors 6502a
 
xShane's Avatar
 
Join Date: Nov 2012
Location: United States
Quote:
Originally Posted by mduser63 View Post
There are some who don't do this and will disagree with me, but you should always use the appropriate getter and setters instead of accessing instance variables directly. The only exception to this is inside the implementation of a custom setter/getter (where you have to do direct ivar access of course), and inside initialization (init) methods. Apple's document on encapsulation in Objective-C explains all this (and more).
Yeah that's what I thought. I thought I read somewhere that Apple might even reject your app if you access directly.
__________________
Macbook Pro 15" 2.6, 8GB, 750GB, 1GB VRAM
24" Asus display


"Be the change that you wish to see in the world."
xShane is offline   0 Reply With Quote
Old Feb 18, 2013, 12:58 PM   #7
mduser63
macrumors 68040
 
mduser63's Avatar
 
Join Date: Nov 2004
Location: Salt Lake City, UT
Send a message via AIM to mduser63
Quote:
Originally Posted by xShane View Post
Yeah that's what I thought. I thought I read somewhere that Apple might even reject your app if you access directly.
They won't reject it. It's just a matter of good programming practice and style. Anyway, it would be pretty difficult for them to detect. Still, it's definitely good to get in the habit of always using accessor methods.
__________________
27" 2.93 GHz Core i7 iMac, 12 GB RAM
2.3 GHz Retina MacBook Pro
12" 1.33 GHz Superdrive PowerBook G4, 1.25 GB RAM
iPhone 5, iPad 3, etc.
mduser63 is offline   0 Reply With Quote
Old Feb 18, 2013, 05:29 PM   #8
Sydde
macrumors 68000
 
Sydde's Avatar
 
Join Date: Aug 2009
Quote:
Originally Posted by xShane View Post
Also, I'm assuming that I should never access variables declared in header files directly, and that I should use the appropriate getter and setters provided from @synthesize? For example, I enter text in a field, and click a button. I then assign the string in the text field to a variable. I should use a setter instead of directly setting (i.e. variable = string), correct?
"Never" is kind of a bad word. There are exceptions to almost everything. One important one is that you might create an object that contains ivars that are not directly accessible to other objects, in which case you would probably not use @property in the first place.

Consider, for example: you create a queue manager object. The object would probably contain a NSMutableArray to hold the queue, but other objects would not be able to actually see the array, they would only be able to add and pull entries, and possibly clear the queue. In this case, I would see no good reason not to access the array ivar directly from your object's methods.

@property/@synthesize offers two important functions: one is that setter methods can transparent broadcast a notification to other interested objects when the property changes, tremendously reducing the amount of coding you have to do; the other is that accessors are typically thread-safe, unless you specifically mark the properties otherwise.
__________________
You got to be a spirit. You can't be no ghost.
Sydde is online now   0 Reply With Quote
Old Feb 18, 2013, 06:16 PM   #9
mduser63
macrumors 68040
 
mduser63's Avatar
 
Join Date: Nov 2004
Location: Salt Lake City, UT
Send a message via AIM to mduser63
Quote:
Originally Posted by Sydde View Post
"Never" is kind of a bad word. There are exceptions to almost everything. One important one is that you might create an object that contains ivars that are not directly accessible to other objects, in which case you would probably not use @property in the first place.

Consider, for example: you create a queue manager object. The object would probably contain a NSMutableArray to hold the queue, but other objects would not be able to actually see the array, they would only be able to add and pull entries, and possibly clear the queue. In this case, I would see no good reason not to access the array ivar directly from your object's methods.
While, I agree that there are exceptions, as I mentioned in my reply, I still think one should use accessor methods even for internal/private values. You can declare an @property in a class extension to keep it private (just like any other methods). Your example is actually a fairly common scenario. You may not want public access to the underlying mutable array, but it's quite common that you want Key Value Observing (KVO) to work for the associated property. It's a lot easier to make sure this works right if you always call the setter when setting it.

Quote:
Originally Posted by Sydde View Post
@property/@synthesize offers two important functions: one is that setter methods can transparent broadcast a notification to other interested objects when the property changes, tremendously reducing the amount of coding you have to do; the other is that accessors are typically thread-safe, unless you specifically mark the properties otherwise.
Minor nitpick: Accessors are atomic by default, but that's not the same as truly thread safe. It simply means that a if one thread calls the getter at the same time another thread is calling the setter, the getter will return a non-garbage value. It doesn't prevent race conditions (e.g. two threads trying to write a different value simultaneously), nor does it guarantee data integrity in the case that multiple properties interact with each other.
__________________
27" 2.93 GHz Core i7 iMac, 12 GB RAM
2.3 GHz Retina MacBook Pro
12" 1.33 GHz Superdrive PowerBook G4, 1.25 GB RAM
iPhone 5, iPad 3, etc.
mduser63 is offline   0 Reply With Quote
Old Mar 17, 2013, 02:44 AM   #10
Sydde
macrumors 68000
 
Sydde's Avatar
 
Join Date: Aug 2009
Quote:
Originally Posted by mduser63 View Post
While, I agree that there are exceptions, as I mentioned in my reply, I still think one should use accessor methods even for internal/private values.
It occurs to me that Apple has implemented some form of "mobility" for objects, meaning that the pointer for an object may actually be an indirect reference, akin to the classic Mac "handles". This would explain why they are encouraging the use of accessors, because object context (ivars) may no longer be always at a consistent address. By using accessors instead of direct references, code maintains forward compatibility. Is this correct?
__________________
You got to be a spirit. You can't be no ghost.
Sydde is online now   0 Reply With Quote
Old Mar 17, 2013, 02:43 PM   #11
firewood
macrumors 603
 
Join Date: Jul 2003
Location: Silicon Valley
Quote:
Originally Posted by xShane View Post
Also, I'm assuming that I should never access variables declared in header files directly, and that I should use the appropriate getter and setters provided from @synthesize?
Apple's own sample code occasionally accesses ivars directly. In some places, for instance C callbacks found in some of the iOS frameworks, this is required. There are also potential performance differences.
firewood is offline   0 Reply With Quote
Old Mar 17, 2013, 03:53 PM   #12
Starfia
macrumors newbie
 
Join Date: Apr 2011
xShane,

Objective-C is a really elegant and fun language to learn and use, and Xcode has evolved to the point where tricky things like memory management and tracking down bugs has become a fraction of the burden it once was.

App Delegate:

There's no theoretical reason why you can't write all your code within the app delegate -- after all, even if you write a program made of a hundred files, they're ultimately concatenated into one file anyway. But, in the interest of creating code that's clear, intuitive and reusable, Apple will tell you to follow the "Model View Controller" design pattern.

"Views" are the kinds of objects you manipulate in Interface Builder -- designed to perform highly standardized tasks and reporting them through Actions to their Targets, but otherwise have no innate intelligence.

The "Model" is the object that stores the custom data relevant to your app -- like a deck of cards and the order they're in -- as well as custom methods designed to make it easy for other objects to ask about or modify that data.

"Controllers" are the intelligent link between Views and Models. Tasks for a Controller could be summarized by phrases like, "the user just tapped the 'take a card' button, so I'll call the method in the Model that provides the name of the next card," or "now that I have the name of the next card, I'll display that name to the user in the appropriate view." (Confusingly, a "View Controller", such as an instance of UIViewController, is a "controller." It's called a "View Controller" because it's responsible for managing a View, as well as the subviews it contains. Anyway.) Typically, you should start a new project an Xcode template that already includes some kind of UIViewController object. I would suggest -- just to nurture habits -- that even if you write all your code in one place, you do it in the implementation file for your main View Controller.

Anyway, that was a huge answer, but I hope it gives you some kind of vague orientation. The enormous advantage of the Model View Controller pattern is that, if it's done properly, you could -- for example -- reuse the model elsewhere with entirely different views and controllers with virtually no trouble. You're *already* using view objects that have been designed with this kind of reusability in mind.

With the templates available in Xcode, simple apps may not even need to modify the App Delegate file. However, you can use it to handle things like changes related to the app's state when the user is multitasking.

Outlets and Actions:

View objects use Actions to call methods that you write in code. Almost always, they call these methods to report on some interactions with the user. Your code uses Outlets to access the views they point to, usually in order to adjust and configure them in response to that interaction, or to changes in your Model. Put another way, messages sent with Actions go in the direction from the user to your code, and messages sent using Outlets go in the opposite direction: from your code to the user.

Directly accessing instance variables:

Having accessor methods and property declarations is usually preferable to accessing instance variables directly. There's never any harm in using accessors, even when the entire business of doing so is hidden within an object's implementation. In your case, yes -- use code like "self.variable = string" instead of "_variable" = string.

I've found there's almost never any need to declare instance variables in header files -- you should think of header files as something presented publicly to other people (or to anthropomorphize, other objects in your program) with the goal of exposing clearly and at a glance, the competencies of the object. If there are instance variables that are necessary to the operation of the object, but not necessary for other objects to know about, they can be declared at the top of the implementation file using a Category. Other objects should *never* access an object's instance variables directly -- instead, those variables can be exposed in the header file using property declarations.

Getting the most out of Objective-C really depends on your understanding of the concepts its developers had in mind. There are a two great resources to continue orienting yourself:

- Stanford's "Coding Together" course on iTunes U. Even the first class session will help a ton and help demystify some of your main questions.

- Apple's documentation. It's designed to be understood, and it's extremely rich and well-written. It's worth wincing and spending a couple of minutes really trying to understand each sentence and paragraph at first, and the documentation for some of the classes provide good models on which you can base your own header files before starting to implement them. It includes a lot of articles on the basics of Objective-C, as well as tutorials and programming guides that walk you through most of these good habits.
Starfia is offline   0 Reply With Quote
Old Mar 18, 2013, 12:08 PM   #13
mduser63
macrumors 68040
 
mduser63's Avatar
 
Join Date: Nov 2004
Location: Salt Lake City, UT
Send a message via AIM to mduser63
Quote:
Originally Posted by Sydde View Post
It occurs to me that Apple has implemented some form of "mobility" for objects, meaning that the pointer for an object may actually be an indirect reference, akin to the classic Mac "handles". This would explain why they are encouraging the use of accessors, because object context (ivars) may no longer be always at a consistent address. By using accessors instead of direct references, code maintains forward compatibility. Is this correct?
No, this is not correct. The pointer value will always be consistent for a given object instance. Besides, objects are always accessed by pointer anyway. Even direct ivar access is actually self->ivar after compilation, where self is a pointer to the structure representing the object whose method is being called. However, direct access can have implications for code forward compatibility.

Quote:
Originally Posted by firewood View Post
Apple's own sample code occasionally accesses ivars directly. In some places, for instance C callbacks found in some of the iOS frameworks, this is required. There are also potential performance differences.
Not everything in Apple's sample code should be taken as the best way to do things. It's written by a variety of different Apple employees, and widely varying coding styles can be seen across authors and through time.

There are some rare cases where direct ivar access is required in API-driven C callbacks. The only one that comes to mind is callbacks on Core Audio's real time rendering threads, where any calls into the Objective-C runtime are a bad idea. Generally, in a C callback, you can pass in an object pointer via the context info parameter, then cast that from void * to the object type in question, and send it messages (call methods).

Direct ivar access is very slightly faster, but the difference is so small as to be irrelevant except in the most extreme situations. In any case premature optimization is a bad thing. If you profile your code and find that accessor method calls are really the bottleneck (again, very rare), then you could think about switching to direct ivar access, but you shouldn't disregard the disadvantages of direct access for some hypothetical, unlikely performance benefit.
__________________
27" 2.93 GHz Core i7 iMac, 12 GB RAM
2.3 GHz Retina MacBook Pro
12" 1.33 GHz Superdrive PowerBook G4, 1.25 GB RAM
iPhone 5, iPad 3, etc.
mduser63 is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Tags
code, objective-c, programming, xcode

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
basic questions stanw MacBook Air 6 Nov 4, 2013 06:41 PM
Basic questions kat.hayes iMac 7 Jun 12, 2013 04:14 PM
Basic Objective-C Cocoa questions? cpuin Mac Programming 8 Jun 3, 2013 08:10 PM
Basic Keep questions stanw Alternatives to iOS and iOS Devices 0 Mar 26, 2013 12:56 AM
A few Basic OS questions snerkler Mac OS X 10.7 Lion 6 Jan 7, 2013 12:07 PM

Forum Jump

All times are GMT -5. The time now is 01:08 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC