How can I press a button to play a custom sound? - objective-c

I'm a complete programming novice and I was wondering how I could have several buttons that play different sounds. I've searched all around and can't figure out this simple task. Thanks!

It's a simple task once you know enough about Objective-C and the Cocoa (Cocoa-Touch on iPhone) frameworks.
Rather than just searching the net for examples you would be better off looking for references on how to program Objective-C and Cocoa.
The steps are:
In Xcode, create a controller class that has a method such as this: - (IBAction)playSound:(id)sender;
Create the UI using Interface Builder.
Place the buttons you want on this interface and configure their labels.
For each of the buttons set a numeric tag (you can do this in interface builder).
For each of the buttons set the target to be the controller and the action to be the method you created in step 1. (You do this by ctrl dragging the button onto the controller object in Interface Builder)
In the controller class, fill out the method by writing a for loop that checks the tag of of the button (which you can get through the 'sender' object and then play a sound based on the tag.
Depending on your level of experience with Cocoa, this might not make sense right now, but if you read through the references and tutorials for Objective-C and Cocoa each of these steps will become clearer and you'll be able to complete this simple task yourself.

Related

Don't Understand Apple's takeFloatValueFrom: Example

I'm no iOS guru but I know enough to build apps. I know and understand the patterns, UIKit, and Objective-C. I'm now learning Mac Development and this little bit of "Cocoa Bindings Programming Topics" has me stumped:
Take as an example a very simple application in which the values in a text field and a slider are kept synchronized. Consider first an implementation that does not use bindings. The text field and slider are connected directly to each other using target-action, where each is the other’s target and the action is takeFloatValueFrom: as shown in Figure 2. (If you do not understand this, you should read Getting Started With Cocoa.)
This example illustrates the dynamism of the Cocoa environment—the values of two user interface objects are kept synchronized without writing any code, even without compiling.
(Emphasis mine)
Huh? Wouldn't you need to create outlets? And an IBAction that goes something like
- (IBAction)takeFloatValueFrom:(id)sender {
self.slider.floatValue = [sender floatValue];
self.textField.floatValue = [sender floatValue];
}
Is this something Mac-specific? How do you actually hook up two controls with target-action in a XIB without writing any code and have their values locked?
When you're setting up an interface in Interface Builder, you can specify that it sends a message to another object whenever it changes in some way. What this example is showing is that you can hook these two objects up such that whenever the slider changes, it sends the message takeFloatValueFrom: to the text field, and vice-versa.
takeFloatValueFrom: is a method defined on NSControl, and both a text field and a slider are subclasses of NSControl.

Global Access to Class instance - Optimal design approach?

OK, here is my situation and I'm really not sure on which design approach to use. So, I'd be glad to read some input on my particular case...
The scenario :
I've got a tab-based application
Initially we create an instance of NSWindowController (e.g. MyDocumentManager) which takes care of the tab creation/manipulation
Each tab contains (= is attached to) an instance of MyDocument
Now, I'm about to implement the menu actions.
For each menu there is a separate Menu Controller (actually a subclass of NSObject grouping all relevant functions), e.g. MyFileMenuController
File Menu's actions are linked to actions in a MyFileMenuController object, via Interface Builder
The question :
How is it possible that MyFileMenuController "knows" about MyDocumentManager (created in my AppDelegate.m), so that we can access current document details and perform all relevant actions? Any ideas? Which approach is preferable?
My ideas :
Passing object from class to class (not sounding that great)
Singletons (although I've honestly never used them, and do not know whether/how it could be my particular case)
Notifications & Notification Listeners
(Looking at it from the opposite side, though not sure) Delegate methods
OK (not sure if that's the best way to do it), but this is what I decided to do :
[[[NSApplication sharedApplication] delegate] MyDocumentManager]
So, as long as an object is part of my AppDelegate, this way I can access it from anywhere.
I would make an initial UIViewController linked to appDelegate.rootViewController.
In this new view controller (just call it "mainViewController") I would put my tabBar and the menuController.
I understand your interface is similar to facebook with a leftBarbutton which makes horizontal scroll and discover the menu. So in the selector for this leftBarButton I would call a method like:
- (void)discoverMenuForDocument:(MyDocument*)document {
// Set menu configuration for specific document
// Make animation to discover menu
}
Where document could be something like:
self.selectedViewController (<-- You cand make this in several ways depending on your code...)
Realize that (MyDocument*) is not an object but just a reference, so in my opinion there isn't any problem doing this.
Good luck!

"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.

how to get uiview to talk to controller

I'm relatively new to Objective-C and Cocoa... I've been trying to understand how to correctly implement the MVC pattern in Cocoa/Cocoa Touch for a long time now... I understand the idea behind it; it makes complete sense conceptually: a model holds the data, a view is what that the user sees and can interact with, and the controller acts as the bridge between the two. View can't talk to the model, model can't talk to the view. Got it.
What doesn't make sense to me is how to use MVC efficiently… if the user can only interact with the view, and does something to interact with it (i.e. for an iPhone app, the user clicks/drags within a subclass of UIView, triggering the "touchesBegan" and "touchesMoved" methods, etc.), how does the view communicate these events to the controller?
I've looked at countless examples and forums online, but have yet to find a simplified all-purpose way of achieving this… I know how to communicate with a controller through buttons, sliders, and other things that you can connect to an outlet, but for things that don't have a target-action mechanism, what's the best way to do it?
Thanks in advance for any suggestions regarding what to do, or where to look.
The standard way in Cocoa to do this is the delegate pattern (cf. UITableViewDelegate). Your view class would declare a delegate protocol and the controller sets itself as the view's delegate. The view then calls one of the delegate methods you defined whenever it wants to communicate something to the controller.
An alternative would be to implement the target-action mechanism for your view yourself. You get this more or less for free if you subclass from UIControl (just call sendActionsForControlEvents:) but it is quite easy to implement a system that works the same way for any custom class.
(Edit: I suppose a third way is to have the controller observe properties of the view (with KVO). This wouldn't work well to communicate touch events but it is a feasible way if you want to notify the controller about a state change or something like that.)

OOP: Designing a menu system

I am currently trying to create a menu system for a game and cannot arrive at any really sound way to do it. There are several menu screens, each of them non-trivial, so that I would like to keep these as separate classes. The main problem I am having is passing control between these menu screens.
I tried building each of the screens as a singleton and call one screen from the other directly, ie. something like [[MainMenu instance] display] in Objective C. This is a bit messy, because (1) I have to write the singleton boilerplate code for each of the menu screens and (2) the classes get dependent on each other, sometimes I have to code around circular dependencies etc.
I thought about making the classes fully static to get around the instance management (which is a bit extra in this case, since there really is just one instance of each screen). But this also looks quite ugly, especially with Objective C having to “fake” class variables by declaring them static.
Then I thought about some “manager” class that would create the instances and pass the control around, but I am not sure introducing an extra class would solve the problem, especially if this class was to be named Manager :-)
I should note that I do have a working system, it just doesn’t feel very nice. By which I mean there is a bit of code duplication going on, if I am not careful the thing might hang, and so on. Any ideas? I am aware that this is underspecified, so that the discussion will probably be more of a brainstorming, but I am interested in the ideas anyway, even if they do not outright solve my problem.
Update: Thank You all for the ideas. What I did in the end:
I reworked the menu contents (buttons, graphics, etc.) to fit under one interface called ScreenView. This is a general interface that looks like this:
#protocol ScreenView
- (void) draw;
- (BOOL) handlesPoint: (CGPoint) p;
- (void) appearWithAnimation;
- (void) disappearWithAnimation;
- (BOOL) hasFinishedAnimating;
#optional
- (void) fingerDown;
- (void) fingerUp;
#end
Thanks to this protocol I was able to throw away all the specific menu screens and create a general menu screen that takes a list of subviews to display and handles all the presentation like drawing, transitions, events and such. This general menu screen does not get subclassed much, because most of the menu screens are happy simply displaying a list of subviews. This would be the V in MVC.
Then I also created a controller class that handles all the events for a certain menu screen. (Obviously the C in MVC.) The root controller class handles the instance management, transitions between menus and some other little things. Most of the menu screens get a customized subclass of the controller that handles the events from the buttons and other subviews.
The number of classes got up, but the code is much cleaner, does not repeat itself and is less prone to errors. The instance management is still not perfect, but I’m reasonably happy with the design. Once again, thank to all who answered.
One of the tricks I learned to decent design is always separate your data from your code. This will do WONDERS for your specific problem.
By this I mean that the menu items (strings) and relationships between the menus should be stored somewhere either in an array or a separate file (and read into an array).
You then use this array to instantiate all your menu classes.
Once you recode it to work this way (I've done this with menus), all your code will fall into place, you'll also factor out--90% of your menuing code (each menu will no longer be it's own class, just the same class instantiated with its own unique data.
The target of the menu items are stored in the "data" as well (as method pointers or class instances).
I think a MenuManager class would be the way to go. You'd have one Menu base class which all the menu screens derive from, and the manager would have a pointer to the currently active menu screen. It could also, for example, keep track of previous menu screens for easy use of back buttons on menu screens in arbitrary menu screen calls. Maybe just use a std::vector for that so you don't have to recreate the previous menu screens when going back (this would also prevent loss of entered information, like in an Options menu with an Advanced submenu).
Putting all the contents of the menus into a dictionary, dumping to a plist and reading each as necessary by the menu screens is likely the simplest route but in all honesty, you should consider taking a more MVC-centric approach to solving the problem. The screens should be for presentation of data not the storage of it. If you provide for a clean separation of the data from the views, the problem solves itself.