Recursive Delegation in iOS—How to Implement? - ios

I have a DataController for my ViewController, which handles loading data from the internet. I set the DataController as the data source for my ViewController, and it works fine. But now I want to display a progress bar as the data loads, so I was thinking of having the ViewController be a delegate of the DataController, and be notified of when loading starts, continues, and ends. Obviously, this recursive delegation leads to a Bad Access while the stack is still showing me assembly. How should I implement this situation?

I've never used this exact dataController pattern you're mentioning, but my common implementation for something along these lines is:
Declare a NSArray or NSMutableArray as a member your UIViewController subclass
Create a class that using ASIHTTP or NSURL to load data from the web, and set that class as the delegate for the ASIHTTP or NSURL
Create a protocol in that data access class that your UIViewController adheres to
Create an instance of that class in your UIViewController, and start the fetching process (asynch)
When the requests complete (or are giving progress notice) to your data access class, send that information via delegate to your UIViewController
When the request fully completes return the list of items to a delegate method and store that data locally in the array from step 1.
There are various ways to do this depending on your circumstances, but I just wanted to give you an idea.

Never mind; turns out the issue was due to a premature release. I'm dealing with objects that should never be dealloced (data source and root view controller) and I set up the delegation after both are created, so there's really no issue here.

Related

iOS: class instances connection and architecture with multiple UIViewControllers

I have a theoretical-practical question. I can't understand how I must do. I have a class let's call them DataManager that manage all plist writing-reading things and I need to get access to plist (i.e. work with that DataManager class) from different UIViewControllers.
I also have one class, I call it ModelManager, that is work with all kind of "utilities classes", include my DataManager. ModelManager works only with one complex UIViewController right now, let's call it MainUIViewController for clearness. And for now, I thought that all calls from UIViewControllers will be comes to ModelManager and from it to end-call classes. But now I'm confused.
Here is an illustration of my architecture:
I'm see different approaches and don't know how to decide and if there is some rules or guides for that. So, here is my choices:
1) I add some interface to ModelManager and from my another UIViewController (not a MainUIViewController) allocate and initialise it.
2) I add some interface to ModelManager and create a property with reference to ModelManager in another UIViewController and when segues performs set this property from MainUIViewController.
3) Work with DataManager itself and allocate and initialise it from another UIViewController
4) Work with DataManager itself and create a property with reference to DataManager in another UIViewController and when segues performs set this property from MainUIViewController.
Which approach is correct?
I know that this is some kind of depends from developer which approach to choose, but I never read and didn't find any tutorial or guide of how to develop multi-class architecture.
Ask me about any circumstance that you want to know.
You can use a singleton or you can instantiate one instance of the class in your app delegate and pass it around to all your view controllers via #propertys on each controller. There's no right answer, it's mostly a matter of preference. I prefer to make my ModelManager/DataManager type classes singletons, but a lot of people are rabidly opposed to singletons. However, if you work with Cocoa for any length of time you'll find that it's full of them (NSUserDefaults, NSFileManager, UIDevice, probably some others I'm forgetting).
Here's a good example on how to create singletons: http://www.galloway.me.uk/tutorials/singleton-classes/
BTW: Once you have your singleton, learn how to use KVO to make your view controllers respond to changes in the model. It's pretty fantastic once you get the hang of it. http://nshipster.com/key-value-observing/

Casting of [UIApplication sharedApplication].delegate

I've got a test project to use the private data object on several view controller.
(I've downloaded it from web & git-hub)
- (ExampleAppDataObject*) theAppDataObject;
{
id<AppDelegateProtocol> theDelegate = (id<AppDelegateProtocol>) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
return theDataObject;
}
First question is, theDelegate was casted with AppDelegateProtocol, even this applications UIApplication delegate name was ViewControllerDataSharingAppDelegate, and there's no warning. I can't under stand why, maybe it's because that was a id type?
(AppDelegateProtocol is a custom delegate protocol he declared in the AppDelegate.)
Second, it shows this kind of code on every view controller, and it seems like just a single-ton pattern.
I don't think this is not the best way to transfer data between view controller.
Which is the best way to transfer object data type?
Thanks.
Creating a protocol decouples the code somewhat from the specific implementation. You could conceivably have several applications, each of which uses its own custom class as an app delegate, but all implementations conform to the AppDelegateProtocol.
I used to use the app delegate to hold global data and methods a lot when I first started in iOS.
However, that fills your app delegate with app-specific code.
I've shifted away from that approach recently, and use a data container singleton (and perhaps a utility methods singleton as well.) As is typical for a singleton, I define a class method that lets me fetch the singleton. I add properties to my singleton as needed to store data, and then just use the class method to get a pointer to the singleton. I write my class method to lazy load the singleton.
Its also easy to make your data container singleton persistent by making it conform to NSCoding. Then every time you get moved to the background, just save your singleton somewhere. On app launch, read it in.

Delegation pattern in Obj-C - Am I doing it wrong?

So in my app I have the following situation:
BackendCommunicatingClass -> (owned by) -> ModelClass -> (owned by) -> HomescreenViewController
HomescreenViewController is a delegate for ModelClass.
ModelClass is a delegate for BackendCommunicatingClass.
Also on when the app launches for the first time, I have this:
WelcomeViewController -> (owned by) -> HomescreenViewController
HomescreenViewController is delegate for WelcomeViewController.
When the user types a username and password in the WelcomeViewController, this information needs to get all the way to BackendCommunicatingClass, and then all the way back to WelcomeViewController to display error if needed. Right now I have implemented this by passing information to each class in the communication chain, until it gets to BackendCommunicatingClass. The result is a lot of duplication of protocol methods and I feel like I'm doing it wrong.
What do you think?
Well I understand it is not the clearest solution, but without seing the code, and the purpose of your program, this what I suggest.
Implement Key Value Observing (KVO) in Back End view controller, observing change in the Home View Controller. As soon as Back end controller detect change in the text field, trough a dedicated variable in Home View controller, it fires all the operation it has to do.
When back end finish, it sends a NSNotification with the result of the operation. Home view controller which you have made listening to such custom notification, react to that and display error message or other staff.
It may sounds complicated, but KVO and notification are easy to implement, and there are plenty of docs and tutorial on the net.
If there is a clear 1:1 mapping of what those delegate protocols provide AND the delegate does not deal in UI stuff that nothing except the directly owning view controller should be concerned with, you could pass the delegate along to the end of the chain and set it directly as a delegate. This is what delegates are for - being able to allow an otherwise unconcerned object to communicate with another object.
That said, depending on how strict your layering policy is, you may prefer to encapsulate the information at every step by having different delegates.

Multiple Delegates in iOS

I am making an object that goes to download stuff for all of my view controllers. The object is singleton instance and has a callback method with received data once the download is completed. It also has a delegate property so that it knows which object to call back to after the download is done.
There are multiple controllers that use this shared instance, and my question is how to call back to the correct view controller that requested the download.
My approach is to use delegation, but the problem is that since other view controllers are also its delegate, the download object could call back to every object and this will be hard to track.
I've worked on projects where people have attempted to use multiple delegates and it's basically a bad idea. The delegate pattern is about a 1 to 1 relationship between a class and it's delegate. Whilst it is possible to achieve some level of multiple delegation through switching the delegates in and out, it's more likely to lead to unpredictable behaviour and bugs.
My recommendation would be to change how you are thinking about this. You have two options as I see it:
Switch to an Observer pattern where you can register multiple observers which your main class can interact with. This is useful where your observers all implement the same protocol and where your main class wants to be aware of the observers and interaction with them.
Broadcast NSNotifications to indicate state changes and events. Here is a more decoupled approach because the main class does not need to know who is listening and does not directly interact with them. Other can start and stop being notified at their leisure. It also has the advantage that you do not need to create or implement a separate protocol. Instead you register the classes that need to know about changes with the NSNotificationCenter which in turns handles all the routing of notifications for you.
It actually sounds like the delegate pattern might not be the best approach here.
I would look into NSNotificationCenter instead.
The basic idea is that your singleton doing the net connection posts a notification (with something like postNotificationName:object:userInfo:) , saying that new data is available. Within this notification, you can pass a dictionary object (userInfo) that holds the data you've fetched, or info on what parts of your Model contain updated data.
Then, your other view controllers can register themselves to 'observe' these notifications by calling addObserver:selector:name:object:. Generally speaking, when a vc becomes visible I call addObserver, and removeObserver when it's being hidden or transitioned out.
Good luck!
Delegation doesn't seem like the right solution to this problem. How about requiring the requesting view controller to provide an object (its self) and a selector for you to call as a completion notification? Of course, you'll need a place to store that object and selector until the download completes. Hopefully you have (or could create) an object for this.
i recommend to use one of these ways
observer:
when use data that you want to inform other object are near to primitive ones.for example when you are using 'NSMutableArray' you can not inform the change in one of object by the standard implemented pattern at least you need to implement one for your self that is not reusable that much
Notification
when your interaction with destination object (those need to be inform) is in one-way.it means you don't need any acknowledge or other data back from them.
delegate
when there is one object to inform at each time step.
note:block use for success and fail is not a pattern to broadcast data its about to queue task when you don't know when they are finishing or failing like network operations
EDIT:
how to create notification | multi delegate issues and implementation
While I agree with most of the answers here, if you did actually want to achieve multiple delegates you could potentially declare an array of delegates and send messages to all delegates within that array. If your protocol has optional delegate methods you safely check using responds(to aSelector: Selector!) -> Bool before invoking (being mindful of memory management, as those delegates would be strongly referenced in the array). Again I do agree that multiple delegates is likely a bad architectural idea and using blocks or notification center would suit your needs better.
One approach, which works for me if you only have one other object to forward messages to is to create a forwardingDelegate This does not end up with issues of hard to debug ordering of delegates and it does not unnecessarily create a dependency on the other object. Keep in mind, if you have many objects then this might not be the best approach, it is mainly for one additional object but this could be extended to support an array of objects so long as there is one that receives the SDK and forwards it to the other objects [1]. Note that every method that is needed for the forwarded object needs to pass it along, even if it is not used by the forwarding object.
For example, if I need to forward the messages coming from the mapView delegate:
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
// handle this object here.
if ([self.forwardingDelegate respondsToSelector:#selector(mapView:regionDidChangeAnimated:)])
{
[self.forwardingDelegate mapView:mapView regionDidChangeAnimated:animated];
}
// or handle this object here.
}
[self.forwardingDelegate mapView:mapView regionDidChangeAnimated:animated];
The forwarding property would be declared like this.
#property (nonatomic) id<MKMapViewDelegate> forwardingDelegate;
And the other object would adopt the protocol as if it were receiving the original message.
[1] The array approach for multiple delegates may get tricky because then you don't have as much control over what order the delegates get called, as was mentioned in other posts.

iOS - Core data - completion handler

Overview
I have a iOS project that uses core data
The core data is used by view controllers as well as for notifications
Implementation
Created a singleton class for database activities called DatabaseEngine
In the appDelegate didFinishLaunchingWithOptions, DatabaseEngine is instantiated
DatabaseEngine contains properties (delegate) for the view controller and for notifications
In the viewDidLoad of the view controller I am setting the DatabaseEngine delegate to the view controller instance
Once the database is opened, the completion handler (through the delegate properties) calls the methods to setup the view controller and notifications
Concern (Timing issue)
I am concerned there might be scenario (a timing issue), where the DatabaseEngine is created first and at that moment the view controller's viewDidLoad would not be executed, and therefore the DatabaseEngine delegate would not initialized, therefore the database would execute the completionHandler but since the delegate is nil, no tasks would be done
What I have done to address the concern
Inside the view controller's viewDidLoad, I am checking if the Database is up and if the view controller is not loaded, if yes then i execute the tasks (setting up the views of the view controller) again.
Note- I am NOT using threads explicitly but based on my understanding completionHandler is executed asynchronously.
Question
I have tried it several times, and the view controller data is loaded correctly and there seems to be no timing issue. I even tried looping through a large value(to create a delay) and still there is no timing issue. I wonder why ?
Is my implementation a good design or is there a better way to do this ?
Is that the correct way to address my concern ?
Your design is a bit convoluted, but seems solid. (I prefer to have core data managed by the app delegate, but your approach is just as fine if you prefer it.)
I would, however, use the usual pattern of lazy initialization of your DatabaseEngine class. In this way, when it is needed and really does not exist, it will create itself and do the necessary initialization routines while the view controller will wait until the call to the engine returns something.
// in view controller viewDidLoad, e.g.
self.managedObjectContext = [databaseEngine managedObjectContext];
If the context is not initialized, it will happen here.
I think the best approach too is to have your app delegate manage the data. Seems like the best approach, and it is what a default CD application template does.
I would look into using MagicalRecord, which is pretty amazing if you ask me. With MagicalRecord you just call [NSManagedObjectContext MR_defaultContext]; and you get the default context just like that. MR also has amazing class methods for free like
NSArray *array = [SomeObject findAll]
which returns an array with all your CD objects. You can even set predicates, etc. and it's quite fast.

Resources