Cocoa: Actions Processing - objective-c

the book which I study, to transition from C++ to Objective-C, places all the Action Methods into Application Delegate class.
The sample code within the book works. However, I am thinking, what if I have 100, or in extreme cases 500, controls in my application. Will all the controlls' actions be processed in the same Application Delegate class? This look to me as very messy.
Could you, therefore, help me to answer my question, please:
If I have many controls (buttons, processing bars, fields ... ) in my application, is Application Delegate the only and correct place for processing all the action methods?

No.
Books use the Application delegate because it is a convenient place to put example code.
As you write your own programs, you'll have your own hierarchy of controllers to receive action messages.

Related

How does user input fit into Apple's MVC pattern?

I'm a little confused about input processing in regards to Apple's MVC pattern. According to Apple, your objects should be divided into model objects (which handle the data), view objects (which display stuff), and controllers (which bind the two and also process events and input). However, many of Apple's native UIKit views — UIScrollView, UIControl objects, etc. — do all the input processing themselves, possibly letting their controllers know about it via delegates and data sources. This really confuses me. In my mind, the sturdiness of the MVC triad depends on both the model and view being fairly dumb (and thus easily swappable). When all the OS-level event complexity is centralized in the controller, you have a very nice separation of concerns. On the other hand, adding input processing to the view seems to turn it into a sort of controller of its own.
Am I missing something here? What's the correct way to think about this?
User Input is part of the View in the MVC pattern. They directly interact with the user and provide their data, either on request or through delegation, to a Controller, which might then use that input to affect changes to the Model.
"Dumb" and "easily swappable" are not necessarily the same thing.
Buttons contain a lot of functionality that we don't want to rewrite in every single controller: tinting of the image to indicate highlighting, allowing for cancellation if the tap strays a certain distance before touch-up, etc. Scroll views contain a lot of physics.
In other words, "which display stuff" is a mischaracterisation of view objects. UIView -- the base class -- just provides event data, but subclasses provide higher-level data such as "the button was tapped" or "the scroll view decelerated to a stop".
One thing to think about is your perspective.
When most of us code, our Model is a data object (maybe backed by files or databases, etc), our View is a UIView (possibly setup/configured in Interface Builder) and our Controller is the UIViewController.
What if you weren't coding an app though? What if your world was a UITableView? You can still have a basic MVC separation. Your Model is represented by the UITableViewDataSource protocol, your View still a UIView with it's setups and configurations and your Controller is the UITableViewDelegate protocol. All the pieces there and even separated, the separation is just different than when using a UIViewController. You can see a practical example of the separation a data change. When you the data in the data source protocol nothing happens. You have to call a reloadData method on Controller bit for the table to realize data was changed.
The smaller the item, the harder it will be to see the MVC pattern. A "button" would be a lot harder to use if it was broken into 3 different objects, but you can use MVC patterning inside a single object to create well encapsulated. A UIButton has it's Model in the form of a both public and private properties, a View (UIView still) and a Controller which is bunch of code that accepts events and makes modifications to the View and/or Model as appropriate.

XCode/Cocoa Objective-C - A couple questions

Sorry for the stupid post, but I am new to Objective-C programming and Cocoa and have a couple of questions which I can't find the answers to, I'm hoping someone can enlighten me.
Firstly, in XCode, when using the Interface builder, when I want to create a new object I drag the object to my 'assets'. However I can't specify methods or anything without manually creating a new class file. Is there any point using the interface builder's 'object'?
The first app I built to test things with, I put most of the code in the AppDelegate class files. Research has shown me that the AppDelegate's purpose is simply handling application events like launching and closing. Was I wrong in putting the methods in this class? Does it make any difference?
Finally, if I have several class files created, each handling their own functionality with an interface built and linked to the classes, then what do I do with the 'main' file? It seems to me that the 'main' file and 'appdelegate' class files will be for the most case left as-is?
I hope that makes sense. Again i'm sorry for the silly-sounding questions but I can't find any answers.
Thanks in advance everyone!
Firstly, in XCode, when using the Interface builder, when I want to create a new object I drag the object to my 'assets'. However I can't specify methods or anything without manually creating a new class file.
Sure you can. Just set the class of the object using the inspector.
Note that you can only connect nib objects to an outlet or action. You can't specify any random methods, nor should you—the whole point of the IBOutlet, IBOutletCollection, and IBAction keywords is to declare in code that these properties/methods are used by a nib.
Is there any point using the interface builder's 'object'?
Yes, but pretty rarely. Usually you create objects in code and connect outlets to them.
The application's delegate is one object you may want to create in the MainMenu or MainWindow nib, if you build your application that way (the iOS templates have changed away from it for some reason).
The first app I built to test things with, I put most of the code in the AppDelegate class files. Research has shown me that the AppDelegate's purpose is simply handling application events like launching and closing. Was I wrong in putting the methods in this class?
Probably. The application's delegate generally should only handle business relating to the NS/UIApplicationDelegate protocol.
On the flip side, it's OK to make your root view controller the application's delegate, if it makes sense to do so (and the NS/UIApplicationDelegate implementation code is not too voluminous). The question you have to answer—and only you can answer it for your application—is whether you are making your root view controller the application's delegate or the application's delegate the root view controller. If in doubt, keep them separate.
Does it make any difference?
Long-term, yes. It's very easy, especially in the class of the application's delegate, to create a Big Ball of Mud class—one without well-defined and clearly-delineated responsibilities. Take dynamite to such a class as soon as possible.
Finally, if I have several class files created, each handling their own functionality with an interface built and linked to the classes, then what do I do with the 'main' file? It seems to me that the 'main' file and 'appdelegate' class files will be for the most case left as-is?
Yes. They're boiler-plate.
If you haven't written any code in the application's delegate (or have removed everything you had put there into new and better-delineated classes), such that all that's left are empty method bodies or none at all, you can safely remove the application's delegate. You can always create it again later if you change your mind.
Note that if you delete your application delegate class, you should also change the main.m file—or the MainMenu/MainWindow nib, if you have one—to not refer to it. Your application won't build if your UIApplicationMain call (or any other code) refers to a class that doesn't exist, and it will crash if your MainMenu/MainWindow nib (or any other nib) refers to a class that doesn't exist.
There is no shame in your application having a delegate if you need it to, but if you don't, removing it and the class you were using for it eliminates future temptation to stuff code there or use it to store third-order globals.
The point of using objects in interface builder is to connect methods of the object to UI elements.
It partly depends on what your methods are doing, but for the most part the app delegate class is going to be left alone. It isn't an actual requirement (your program will work either way) but it is common practice because it generally creates more maintainable code. The app delegate should just handle the application events ( using other classes to do any complex logic or heavy lifting ).
The 'main' file will most likely not change. I can't think of any reason to do so, but I wouldn't rule it out for some advanced cases.
To be honest I only used the Object thing in IB once, when I wanted a separate object to have some UI bindings.
About the app delegate and main file, yes, you'll leave them as-is most of the time. But if you try to do something besides test apps you'll need to handle open events to, for example, connect to a server, ask the user for a review, increment some launch counter, etc... Those are just examples!
The main file I advise you to left it alone and use the object oriented tools provided. You should have a view controller hierarchy, isolate your views from the data, and use the view controller to comunicate between view and model. Read about MVC if you want more info on how your application should be organized.

Multiple IBActions for a single UI event

I'm a bit embarrassed to ask this one... if I want two very different things to happen when, say, a UIButton is used, can I hook this up in Interface Builder? I can't find a way to add multiple actions to the event.
The obvious answer is to have a single action connected, and perform both methods in the same block of code. But I quite liked the button action being connected to 'saveItem' instead of some generic 'buttonPressed' method.
I suppose I could also add the actions in code.
Unfortunately, there's not a way to do this with the builtin UI classes. You'll have to hook up to a single IBAction, then call through to the methods you want to call.

Registering all view controllers for NSNotifications

I have a custom graphic that is to be displayed to a user when an event occurs. The graphic needs to be displayed on whichever viewController is currently being displayed to the user.
The way i have programmed it so far is by adding to ALL viewcontrtollers:
1) the .h file for the custom graphic class
2) an observer for the NSNotification event that is raised
3) the method which actually draws the graphic.
This doesnt feel like a very efficient way of doing things and i was wondering if anyone has a better way of doing things?
To me it sounds like you've done it in a fairly sane way. The only other way I can think is to just add the graphic to the window which would then overlay on the current view controller and you'd only need to have one object listening for the notification. You could use the app delegate for instance. But then you would have to worry about rotation of the screen yourself when adding the graphic over the top.
What you are doing is correct .. The only thing you can improve is to mauve the drawing graphics part to the custom graphic class.. (if you are not already doing so...
just Make a UIViewController variable as a member variable to the graphics class..and then set it up to the current view displaying..after you receive the notifications..and the class will itself draw the code based on the ViewController you set it up to
The reason it doesn't feel efficient is that you're duplicating a lot of code. That's more work at the outset, and it creates a maintenance headache. You should be taking advantage of the inheritance that's built into object oriented languages, including Objective-C.
If you want all your view controllers to share some behavior, then implement that behavior in a common superclass. Derive all your other view controllers from that superclass, and they'll all automatically get the desired behavior. Your superclass's initializer can take care of registering the view controller for the notification(s) that you care about, and -dealloc can unregister it. This way, you don't have to clutter up each view controller with the same repeated code, and if you want to change the code you only have to do it in one place.

"Global" UIImagePicker Functionality for Multiple Classes

I'm working on an app that (among other things) uses UIImagePicker to grab an image from the device once the user has selected the SourceType by tapping the appropriate button. Different sections of the app will need to use this functionality, as well as the variable holding the image information once selected. When I first started the project I had all of my code to do this in a single class named ViewController. I'm now working on moving the individual sections of the app into their own classes, but I'd like to be able to have them all use the UIImagePicker functionality from a central location.
Along with the necessary UIImagePickerController methods and protocols, I have a method that presents a view with buttons for each available SourceType. Each of these buttons then send a message to methods to show the appropriate picker (or the camera). Once an image is selected, it is applied to a variable for use by the different sections.
I wanted to get suggestions on the best way to approach this before I went to deep down the wrong rabbit hole.
Thanks!
If a lot of your classes use this functionality, you can create a superclass (itself being a subclass of UIViewController).
This class will expose some method to launch the process you described, and some other to gather the information collected.
If you don't want to use inheritance, or you already to with another class, you can also create a separate class responsible for this process.
This class, which is not necessary a UIViewController, has to be instantiated and then called the same way the superclass described above.