Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for using CoreLocation in models vs controllers

I am trying to figure out the best way to architect my app. I current have a wrapper class around CLLocationManager that sets itself as the delegate and handles all the extra setup and business logic we need. It also is a singleton (sharedManager).

I'd like to be as true to MVC as possible and push as much logic into my models, but I'm not sure of the best ways to do that. Currently both controllers and models are getting the sharedManager and calling methods on it such as checking location is available before presenting a modal (controller) or getting current location before making a REST call (model), but this feels very coupled and difficult to test.

I'd like to use dependency injection as much as possible to avoid constantly querying the singleton method in all parts of my code, but I can't figure out the best way to do it.

Some ideas I've had:

  • Convert my CLLocationManager wrapper to use notification to talk to all parts of the app to improve decoupling. I could then make start/stop calls using the singleton but have my controllers/models react to changes by listening to notifications. This still doesn't avoid having to use the singleton all over the place.

  • Only use the singleton in the controller and pass the needed location data to the model by setting properties. This feels like it would make my models easier to test but not my controller and putting Core location code in controllers feels icky too.

  • I could pass an instance of my custom location manager wrapper around by setting properties on both models and controllers, but that feels a bit tedious and stills leaves the question as to where do I create the initial manager?

I'd love some advice from people who have thought about this issue more in depth. All ideas are welcome and appreciated!

like image 707
Danny Avatar asked Jul 09 '14 13:07

Danny


People also ask

What are the two controller actions exposed by the homecontroller class?

The two controller actions exposed by the HomeController class, Index () and About (), both return a view. A view contains the HTML markup and content that is sent to the browser. A view is the equivalent of a page when working with an ASP.NET MVC application. You must create your views in the right location.

Should we use the repository pattern in controllers?

The repository pattern is a great way to hide our data access logic and create a separate layer for it, but still, we shouldn’t use it in our controllers directly: While something like this is entirely okay for simpler projects, you can imagine it becoming a garbage pile very soon on complex projects with multiple team members.

What should be in a controller model?

A controller should only contain the bare minimum of logic required to return the right view or redirect the user to another action (flow control). Everything else should be contained in the model. In general, you should strive for fat models and skinny controllers.

What are the controllers and models folders in Salesforce?

As you might guess from the folder names, these folders contain the files for implementing models, views, and controllers. If you expand the Controllers folder, you should see a file named AccountController.cs and a file named HomeController.cs. If you expand the Views folder, you should see three subfolders named Account, Home and Shared.


1 Answers

I'd like to use dependency injection as much as possible to avoid constantly querying the singleton method in all parts of my code, but I can't figure out the best way to do it.

You answer your own question:

I could pass an instance of my custom location manager wrapper around by setting properties on both models and controllers, but that feels a bit tedious and stills leaves the question as to where do I create the initial manager?

There's nothing wrong with making your wrapper a singleton, and passing around a reference to it to the objects that need it — that's one way of handling dependency injection. You can have a lot of objects depend on its interface, but if you want to back away from it being a singleton, you can do that too.

Your models don't have to know your location manager is a singleton. Maybe only your controllers do. Or you can pick one or a few root place in your application that knows about the singleton nature of the location manager and injects it to dependent components. How you want to do this depends a lot on your existing application architecture. You could make a "finder" for it (makes it a lot like a singleton again) or pass it in as a parameter in constructors -- a method of dependency injection that's sometimes overlooked.

I would also recommend looking onto Key Value Observing and maybe have your models or controllers observe a location property on your location manager. I personally also like using Reactive Cocoa as a "KVO with blocks" library, without necessarily diving head-first into Functional Reactive Programming. ReactiveCocoa can save a lot of headaches associated with the otherwise very powerful KVO system in Objective-C.

I would not advocate using notifications to communicate a core change like a single location. I've had things get quite messy that way. A common pattern in Objective-C programs is "messages-leafward/notifications-appward".

What you have in your location manager wrapper is essentially a location service. It's not a bad idea to put a lot of business logic in those services instead of in models (where it makes sense). For example, if you have business logic around the frequency of location changes propagating to UI changes, or thresholds of movement, those may apply across various different models. Having that common location-related business logic in a location service can really DRY up your models.

like image 104
Fabian Avatar answered Nov 15 '22 05:11

Fabian