|
|
|
|
#1 |
|
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. Last edited by xShane; Feb 11, 2013 at 04:37 PM. |
|
|
|
0
|
|
|
#2 |
|
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. |
|
|
|
0
|
|
|
#3 | |
|
Quote:
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. Last edited by xShane; Feb 12, 2013 at 03:32 PM. |
||
|
|
0
|
|
|
#4 |
|
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. |
|
|
|
0
|
|
|
#5 | |
|
Quote:
__________________
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. |
||
|
|
0
|
|
|
#6 | |
|
Quote:
|
||
|
|
0
|
|
|
#7 |
|
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. |
|
|
|
0
|
|
|
#8 | |
|
Quote:
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.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
||
|
|
0
|
|
|
#9 | ||
|
Quote:
Quote:
__________________
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. |
|||
|
|
0
|
|
|
#10 |
|
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?
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
|
|
|
0
|
|
|
#11 |
|
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.
|
|
|
|
0
|
|
|
#12 | ||
|
Quote:
Quote:
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. |
|||
|
|
0
|
|
|
#13 |
|
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. |
|
|
|
0
|
![]() |
|
| Tags |
| code, objective-c, programming, xcode |
«
Previous Thread
|
Next Thread
»
| Thread Tools | Search this Thread |
| Display Modes | |
|
|
All times are GMT -5. The time now is 01:01 AM.










Hybrid Mode
