I have a UIView subclass acting as an internal "notification" system, that has a label inside that displays the notification text and animates down from the top of the view and back up. I need to create a system that will create a queue of these notifications (that can be added to from anywhere within my app), and display them one by one, but wondering how I should structure it.
Should I use a singleton that manages a queue of these UIViews? or should there be a UIViewController that has a queue? Or something else?
Thanks!
This is usually managed by a data persistence class. You want to separate data layer from view layer in order to maintain it properly. Implement the notification logic by creating a class that manages the notification data itself, in a queue, and just present said data in a view, in any viewcontroller that should display said notifications.
After you create the class that manages notification data, you can either:
Check inside viewDidLoad() if there is a notification in the queue. If true, present it.
Create a timer and check for the queue every couple of seconds/minutes
Get fancy and implement observer pattern so that every ViewController would subscribe to your notification manager class so that it notifies the VC that new data is available. When that happens, it will delegate through a protocol the presentation logic to the view controller (Preffered)
EDIT: If you go for #3 (and you probably should), remember to use weak for the delegate, as you don't want leaked VCs
Related
I am working on a simple app to try out MVVM in iOS. I have only two screens in the app. Screen A displays content and the user can tap on settings button to pull up screen B. Screen B allows the user to change settings which affect the way screen A displays the content.
How should I communicate changes made in screen B to screen A so that screen A can re-display the content based on the setting changes? In MVC, I would use protocols/delegate to communicate changes made in ViewControllerB to ViewControllerA. Since view controllers have direct access to the models, I can just pass the updated model in the delegate call. In MVVM, would the communication happen between ViewModelB to ViewModelA or ViewControllerB to ViewControllerA(like MVC).
If the communication is happening between view controllers, what is ViewControllerB really passing to ViewControllerA? ViewModelA? If so, doesn't ViewControllerB knowing about ViewModelA defeat the purpose of reducing view controller responsibility/knowledge?
Thank you for taking time to read the question!
In a situation like this, I would engineer the data stream as follows:
Both ViewModelA and ViewModelB communicate with some entity from a model layer (the first M from MVVM). Frequently such entities are called "services" and contain persistence/network logic.
When the user opens ViewControllerB and changes some settings, ViewModelB makes respective changes to the model.
ViewModelA observes changes to the same model (via KVO, NotificationCenter, reactive publishers or a good old delegate pattern, whatever suits you best) and reacts to them by updating ViewControllerA if needed.
This way neither of your view models need to know about each other, and your model layer acts like a single source of truth for both of them.
This is a design pattern question.
I have a 'framework' I'm building, and depending on the current displayed ViewController the framework needs to inject a UIButton into that ViewControllers view.
I don't want the ViewControllers to 'know' explicitly about the 'framework', so I was initially using the delegate pattern but that required a 'over-seer' to ensure that when only specific view controllers were loaded, that they knew about the 'framework'.
However, it occurred to me if I could, via a protocol, ensure that all delete ViewControllers fired off the same two custom NSNotifications i.e. subscribeToRequestButton and unsubscribeForButton, then the 'framework' would listen out for those, and upon receiving them, have the view controller object passed to it (via the Notification) so that it can inject the button.
Thereby preventing the view controller from knowing about or having a reference to the 'framework'; it just knows, if it want's that button, to fire those two notifications, and ensure that it implements a method for when that button is touched.
Is this possible or is there a better approach?
The key problems are that
a) I cannot have the View Controllers that need the button know about the framework; as they never have the opportunity to have a reference to is passed to them by some manager class, and
b) The framework doesn't know about the view controllers existence until it receives a notification that is needs to inject a button into something.
EDIT:
I'll just use a singleton pattern with a few public accessor methods for passing data in or querying.
I have many different views in app. While the application state is active I would like to have a generic response to remotenotifications that is not an alertview. One way to do this would be to place the notification observer in uinavigationcontroller rather than in the different view controllers and then place the notification element in navigationcontroller.view. However, thus far nothing appears in navigationcontroller.view when I try to add a label there. Has anyone had success doing this?
If I understand correctly, it seems like you want to show a view whenever your app receives a remote notification and you want to be able to display the view from anywhere inside the app. If this is correct, the best approach would be to create a new UIWindow object and display that as an overlay on top of your app's main window. This answer describes how to create a UIWindow and display it. Additionally, this library does something similar to what you're trying to accomplish.
With iOS 6 Apple added state restoration to UIViewController and related classes. This allows the application to save state when terminated and restore it when the user resumes the application.
Everything seems to work fine, however I have reached a weird scenario which doesn't want to fit into the pattern.
Let's assume we have two view controllers, ViewControllerOne and ViewControllerTwo, both of them store some arbitrary state that is restored successfully. Now let's imagine that ViewControllerOne has a delegate property and that ViewControllerTwo is that delegate (which is a common pattern for modal view controllers). Who is responsible for restoring this relationship? And how is it supposed to be stored/restored?
In my particular case no storyboards are involved, the restoration happens in code, via the restorationClass property. My first instinct was to try and restore the relationship whilst creating the view controller in the restorationClass, however as the restorationClass has no idea of other existing controllers it can't quite restore such a relationship.
Alternatively, if it is the view controller that declares the delegate property, that is supposed to restore the relationship, then how does it now of the controller instance that was restored in some other class?
In short, this seems like a poorly documented scenario and I was hoping someone could shed some light on it.
I would say, the task falls on the delegate view controller to set itself as such, just like you do it before pushing the other view controller.
On how you can accomplish this, you have several options.
You can store a weak reference to your view controllers in a globally accessible location (for example, the app delegate), and use these values in application:didDecodeRestorableStateWithCoder: to set the delegation - this is what this method is for in the API.
Alternatively, you could post a "hereIAmThisIsMe" notification (with self part of the user info) from the top view controller to which the delegate listens and sets itself as a delegate.
Is there anything like this outside of the application delegate? I would just like to be able to do certain things in my view controllers when I receive a notification. Will I just have to import each of them and check the type of class against my current view controllers in order to perform actions on them?
Essentially, if I received a remote notification and I didn't have an exact reference to the top most view controller on the stack, is there a good way to access a class or instance method of that controller? Or maybe even some properties?
Why don't you just send an NSNotification (don't mistake notification center and Apple Push Notifications) to them? You have a nice article here talking about it.