I have subclassed RMMessageComposeViewController : MFMessageComposeViewController. The extra functionality that I'm aiming for is for the MFMessageComposeViewController to be able by itself to present a new message compose controller (over itself).
So I should from one RMMessageComposeViewController instance present a new one. The message result from the new instance should be sent to the parent (or "old" one). So I suppose I need to set the parent message compose controller as the delegate when I'm creating the child ("new" one).
Could someone please help me think this out, what instance variables I need to add (parents, children?) How to setup the child message compose controller?
From the docs:
The message composition interface itself is not customizable and must not be modified by your application. In addition, after presenting the interface, your application is unable to make further changes to the SMS content.
What you're trying to do there is explicitly not supported because of security concerns: It would make it easy for an application to forge messages. While you can probably push a view on top of it, I suspect your app would get rejected from the App Store for doing it.
I wouldn't be surprised if MFMessageComposeViewController prevents an application from creating more than one instance at a time, though I haven't confirmed this.
Related
Lately I have been playing around with the bluetooth framework and grew a strong enough knowledge to start building an application. The only problem is that all the examples I found and all the practice I have made consist in putting the core bluetooth core code inside the same file as the UIView with which the user is interacting.
I would like my future application to have multiple views in which the BLE scan occurs on the background. I initially thought about creating an object with a name similar to bleDeviceFinder and pass this object through each view. However, after thinking about it I realised that if I want something to happen in the current view I need the function didDiscoverPeripheral to have direct access to the UIView objects which it is supposed to affect.
I know it is probably a stupid question, what would be the best way to do so? I was thinking maybe to set and alert and subscribe every view to that alert; is this a good solution?
A quasi singleton BTLEManager that you pass around in the app. It sends NSNotifications for events like discovery, and your ViewControllers observe these notifications. The truth (i.e. list of discovered devices) stays in BTLEManager. Once a viewController has received such a notification it asks the BTLEManager for the list of current devices and then the viewController changes your views accordingly. The Views should never talk to the BTLEManager directly.
That's how I would do it.
I come from a .NET web application background and have just started iOS development. The initial design of my app focuses around the NSNotificationCenter. I was reasonably happy with this until I saw various posts explaining how reaching for the NSNotificationCentre was a common newbie mistake.
Here is a simplified version of the problem I am trying to address:
My application is trying to show a list of messages that are populated using web service calls, think Facebook messaging.
When the app is first loaded it pulls a collection of messages from the server and displays them in a table to the user. The user can add new messages (which get sent back over the API) and the app can receive Push Notifications about new messages which are added to the feed.
The messages are never persisted to disk so I'm just using POCOs for the model to keep things simple.
I have a MessageFeedController which is responsible for populating the message feed view (in a storyboard). I also have a message feed model, which stores the currently retrieved values and has various methods:
(void) loadFromServer;
(void) createMessage: (DCMMessage*) message;
(void) addMessage: (DCMMessage*) message;
(NSArray*) messages;
(int) unreadMessages;
The current implementation I have is this:
Use case 1 : Initial Load
When the view first appears the "loadFromServer" method is called. This populates the messages collection and raises an NSNotificationCenter event.
The controller observes this event, and when received it populates the tableview
Use Case 2: New Message
When a user clicks the "add" button a new view appears, they enter their message, hit send and then the view is dismissed.
This calls the createMessage method on the model, which calls the API
Once we have a response the model raises the NSNotificationCenter event
Once again the MessageFeedController listens for this event and re-populates the table
Use Case 3: Push Message
A push notification is received while the app is open, with the new message details
The AppDelegate (or some other class) will call the addMessage method on the model, to add it to the collection
Once again, assuming the MessageFeed view is open, it re-populates
In all three cases the MessageFeed view is updated. In addition to this a BadgeManager also listens to these events which has the responsibility of setting the app icon badge and the tabbar badge, in both cases the badge number relates to the number of unread messages.
It's also possible that another view is open and is listening to these events, this view holds a summary of messages so needs to know when the collection changes.
Right, thanks for sticking with me, my question is: Does this seem like a valid use of NSNotificationCentre, or have I misused it?
One concern I have is that I'm not 100% sure what will happen if the messages collection changes half-way through re-populating the message table. The only time I could see this happening is if a push notification was received about a new message. In this case would the population of the table have to finish before acting upon the NSNotification anyway?
Thanks for your help
Dan.
In other words, you're posting a notification whenever the message list is updated. That's a perfectly valid use of NSNotificationCenter.
Another option is to use Key-Value Observing.
Your controller (and anyone else) can register as an observer to the "messages" property, and will be notified whenever that property changes. On the model side, you get KVO for free; simply calling a method named setMessages: will trigger the KVO change notification. You can also trigger the notification manually, and, if so desired, the KVO notification can include which indexes of the array have been added, removed, or changed.
KVO is a standardized way to do these kinds of change notifications. It's particularly important when implementing an OS X app using Cocoa Data Binding.
NSNotificationCenter is more flexible in that you can bundle any additional info with each notification.
It's important to ensure that your messages list is only updated on the main thread, and that the messages list is never modified without also posting a corresponding change notification. Your controller should also take care to ignore these notifications whenever it is not the top-most view controller or not on screen. It's not uncommon to register for change notifications in viewWillAppear: and unregister in viewWillDisappear:.
In my opinion using a delegate protocol pattern would be a much better fit for this scenario. Consider the scenario where your "api layer" needs used across many view controllers in an application. If another developer were to be introduced to your code, they would have to hunt around for notificationcenter subscriptions instead of just following a clean 'interface' like protocol.
That being said, your code will work just fine and this is a valid use of notification center. It is just my personal preference for 'cleaner' code to use a protocol based approach. Take a look around in the iOS SDK itself and you will see scenarios where Apple themselves use protocols and use notifications. I feel it is much more easy to comprehend and use the protocols than having to dig around and determine what I must listen to for a notification.
NSNotifications run the receivers code synchronously as soon as they are posted, so a new message during repopulation would join the back of that execution queue. On the whole it seems valid to me, and it keeps a reasonable degree of separation between The view controllers and the model.
Depending on the number of classes that are likely to want to listen for the same information arriving, you may want to use a delegate pattern, maybe keeping an dictionary of delegate objects, but I personally don't feel as though this scales so well, and you also have to take care of nil-ing out delegates if a page is dealloced to avoid crashes. To sum up, your approach seems good to me.
I'm stuck on this step of developing an XCode application: https://developer.apple.com/library/mac/#documentation/General/Conceptual/Mac101/Articles/07_WhereNext.html
What I'm confused about is the role of the AppDelegate class that's created by default when creating a project initially in XCode 4. If I implement a custom controller, let's use the example link above and call it TrackController. Do I make that controller the app delegate? It seems any tutorial I read isn't very clear on this.
So, in AppDelegate, do I create a new instance of the controller class here? And if so, do I then hook up the outlet here? Or do I change the File's Owner to be the controller class? If that's the case, then how's that done in XCode 4?
Not a very well defined question I know, but I'm sure someone knows what I'm talking about.
EDIT
The following screenshot shows what I mean. The blue box is now "Track Controller". I've shown the AppDelegate class in this case though to make it clear. What do I use, AppDelegate.m, or TrackController.m? How should it be done?
EDIT 2
Going back to this, I've uploaded the code to GitHub here as I still haven't figured out how to hook everything up.
To re-explain, I need to figure out how AppDelegate and TrackController all relate and communicate with one another. The concepts are generally new to me and I've read the Apple documentation but they haven't really helped me. I've even had in-depth discussions with experts and I still fail to see how it should work.
My model is Track, then I have TrackController and of course AppDelegate. AppDelegate is instantiating TrackController and I was hoping that it'd be able to open up its window.
What am I doing wrong? Hopefully an expert can help me!
What it's describing is that the application delegate should focus on handling the delegate calls sent to the app.
You actually create a new class to act as the primary controller of the app, and then you add code to call it when the app is finished loading. From there on out, that app is (supposedly) your primary control point (except, of course, when it 'hands off' to another class).
I'm more familiar with how the process works on iOS than Macs, which have to worry about windows, but for an iOS app you'd add code to call your starting view controller from inside ApplicationDidFinishLaunching:WithOptions:. From there, the view controller takes off, and the easiest way to view the entire process is that you start at the view controller (that's how most tutorials handle it, in fact, letting XCode handle the fact that the app delegate creates that view controller).
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.
I am trying to locate a message which I can override and then save changes to my application.
On MainWindow.xib I have placed a UIView and set its class (in interface builder) to be my Custom view TouchDrawView.
In TouchDrawView I have a bunch of code for handling touch events and 2 arrays which track these touch events.
My application is launched by the AppDelegate but it has no reference to this TouchDrawView. It simply launches the application.
What I want to do is save my 2 arrays when the application terminates - I can do this in the TouchDrawView but I don't know what message this UIView gets sent when the whole application is about to terminate and I can't do it in the AppDelegate because it doesn't have a reference to the 2 array or the custom UIView
UIView instances will not get send any messages when the app will terminate.
There's another easy way to get notified of app state changes: notifications. You can register for notifications sent through [NSNotificationCenter defaultCenter].
For older versions of iPhone OS there's a UIApplicationWillTerminateNotification. Beginning from iOS 4 you should also listen for UIApplicationDidEnterBackgroundNotification, to prepare for termination.
The short, unhelpful answer is that a UIView is not sent a message when the application terminates.
You need to think in terms of Model-View-Controller because that's how Cocoa and Cocoa Touch are designed. Of those three, if a message was directly sent to any it would be the controller. In your case that would be the UIViewController that talks to your view.
The bad news is there is no such message there either.
An application shuts down, not an individual screen/view.
There are (at least) two ways of doing what you want to do. Firstly, you could save the state of the view controller when it is released. (That kind of feels wrong to me.)
They way that I do it in my app is to listen for the applicationWillTerminate message in your UIApplicationDelegate and traverse the view hierarchy and save the state of each view controller. When the system starts up you can do the opposite. I blogged about it here.