iOS common objects - ios

I'm writing an iOS app where there is a common object that all views within the app need to access.
I have been creating, and initialising the object within the viewDidLoad event (of the first view controller), and then passing a reference to this object to all other views that need it. This does not seem like the correct way to do things, feels like I'm somehow breaking the MVC pattern since I'm relying that this particular view is always the first to load in order to setup objects that the whole application needs.
I have now modified my app to do the basic object creation and initialisation in the appDelegate "didFinishLaunching...". This is now working and I can access this common object from all of my other views without having to pass around a reference from one view to the other.
Before I go and continue too far, I was hoping to get peoples input on whether this is the correct way to do things, or whether I should be doing anything else? Sorry if this seems like a trivial question, I'm just learning and want to learn how to do things properly.
Thanks in advance :-)

Without repeating what has already been answered, I'd suggest you make your own Singleton object to hold your 'globals', so you don't clutter your AppDelegate with it.
#interface MyGlobalDataController : NSObject
#property (nonatomic, strong) MyData *myData;
+(MyGlobalDataController *)sharedInstance;
#end
#implementation MyGlobalDataController
static MyGlobalDataController *MyGlobalDataControllerSharedInstance = nil;
- (id)init {
self = [super init];
if (self) {
// do whatever needs doing
}
return self;
}
+(MyGlobalDataController *)sharedInstance {
#synchronized(self) {
if (MyGlobalDataControllerSharedInstance == nil) {
MyGlobalDataControllerSharedInstance = [[MyGlobalDataController alloc] init];
}
}
return MyGlobalDataControllerSharedInstance;
}
#end
The first time you access your sharedInstance, the init will be called, so you don't have to worry about timing there.

Putting your global object initialisation in didFinishLaunching is a better idea than having it in didLoad.
Some people will disagree with me here and say you shouldn't have globals full stop, but personally I think having some sort of global state is acceptable. I love a good object-orientated app but there is a balance to be struck between solid OOP and the flexibility provided by having a few globals.
I think ultimately do whatever is right for you, the major disadvantage of having a global state is that it becomes difficult to maintain and has the potential to introduce a lot of bugs / unexpected behaviour especially in a large app, whereas if you stick to the MVC pattern then each view in your app simply does what it is meant to without unnecessarily affecting other parts of the app.
Nowadays, I tend to stick to MVC / OOP principles for the most part, but have an [AppDelegate]sharedAppDelegate] singleton I can use to access variables at certain points. I have very, very few variables in here but they do come in handy i.e. now my app has a shared 'loading HUD' which is managed by this class, and my sharedAppDelegate also contains a lot of static methods for initiating HTTP, parsing JSON etc which saves a lot of time.
One alternative to having global information in your appDelegate is using NSUserDefaults to store key-value information
Hope that helps anyway, like I said some people will disagree with me but ultimately it boils down to personal preferences, and where the balance for you in terms of rigidity to the MVC model versus flexibility is

Related

Expensive Object management in Swift

I have been looking at Swift the last couple of days and it looks good, I am confused on a point though even after review of the guide Apple published.
I understand that memory management in Swift uses ARC and therefore quite safe, however in situations where I'd like more fine grained control of object creation and destruction I'm slightly confused.
Take these two simple examples:
In ObjC, when you'd (for example) like a UIViewController you intend to push to stay around for the lifetime of your app and only be created once (say because it's expensive to create), you'd make it a property and then wrap it's Alloc Init like this:
if (!self.myProperty)
{
self.myProperty = [[MyObj alloc] init];
}
This way it only creates once, keeps state and the same object instance can be reused indefinitely, yielding known object references, and good performance not having to recreate each time the viewController goes out of scope.
Another example of this is with NSMutableString, vs Swifts String.
You can set an NSMutableString's string many times and it will keep the same object reference, however this doesn't seem to be the case with a Swift String when changing it.
This may just be 'deprecated thinking in Objective C' but is there a best practice with regard to keeping around expensive objects or to keep state (same object) for certain objects during the lifetime of their usage.
I think what you're looking for is a "Lazy stored property":
The example in the swift docs is:
class DataManager {
#lazy var importer = DataImporter()
var data = String[]()
// the DataManager class would provide data management functionality here
}
and it says about #lazy:
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the #lazy attribute before its declaration.
The comment about NSMutableString is a little different, you can continue to use NSMutableString in your swift code, but Apple are encouraging developers to use the Swift built-in types whenever possible :)
see the "String Mutability" section in the swift docs

Should I avoid a Singleton in this case?

I've been thinking about using a singleton on my data class in my current app. I've also been thinking of reasons not to use the pattern and currently I am stuck in the middle.
The reason I am for the singleton in this case is due to accessibility to methods and properties easily that I need to use more than once throughout the app. I could use the appDelegate for this but that muddles up the area of concern as these methods / variables have nothing to do with the app state - more to do with user input. The data will be persisted with eventually with NSUserDefaults - which is a singleton already.
The reason I am against it is because its another singleton to an app that already bass one (The appDelegate)
My question:
Would using another Singleton to access the data model be the correct way / acceptable way of doing it - or should I look at another approach?
I personally think there would be nothing wrong with a singleton as a data model - using the app delegate to instantiate it when the app starts and then access its various methods / properties when I need them throughout the app. This would be the only other singleton in the app (Maybe another one for user management - e.g.; logging in / out / profile / credentials, etc? )
Any thoughts?
Thanks all!
There is no problem having multiple singleton classes within ios, in fact in many of my projects most of the classes are singletons. Normally I have the data access logic and control within a singleton and then actual object classes as instances.
As you have already identified you really do not want to be putting something into AppDelegate that does not apply to the whole app.
From my point of view do not instanciate the class from AppDelegate, simply have the class instanciate itself on first access.
Whenever I am explaining singleton Objective-C to people I always direct them to this site, it may be worth a view for you:
http://www.galloway.me.uk/tutorials/singleton-classes/
It explains only what you need in a really easy to understand way. The bit that does the 'self-instanciating' is this bit:
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
You could use singleton in these case. Don't use delegate to hold values for your app. You may use same singleton for user management also.
Note : Don't use globals unless you need to do so. Singletons and top-level data should be used only when the data they contain truly belongs at the top level.

ARC NSMutableArray pools

I have a pool of objects I keep inside an NSMutableArray so if any other objects want to reference them instead of creating new objects I will simply give it a reference to an object I have already created.
In the past I would monitor retain/release calls on these objects, and when they reached a retain count of 1 (my array only) I would remove them from the array. However I am struggling to do this with ARC because it doesn't let me monitor retain/release, how would I go about doing this?
Creating a way to manage objects based on release/retains calls, it's dangerous. If Apple happens to change the way it works, you are screwed. And apparently, that's what happened, when you start using ARC. There are two things:
1) You want to keep the objects inside the NSMutableArray independently if they are being use by other objects or not. In that case, just create a __weak reference to that objects, and in that way your object, that is inside the NSMutableArray, is kept alive.
2) Once there are not references to the object, just remove it from the NSMutableArray. Add to the NSMutableArray a __weak object. Once the strong one is release, the one inside the array will be as well, although I don't really like this approach as I find it dangerous. If you go for this option, use this to store the objects:
NSValue *weakObject = [NSValue valueWithNonretainedObject:anObject];
[array addObject:weakObject];
In the end, you can simply remove ARC from that specific file, and you can keep the monitoring.
I wouldn't bother with such a complex system. Just work with strong and weak properties and don't try to second guess performance. You are trying to build a memory management system yourself which makes little sense with ARC around. Creating and deleting objects is generally a tiny percentage of performance of any objective-c app; after years of using Instruments to monitor performance I don't worry about this part any more.
First, you should write simple code, intended for humans.
Do not worry about such performance issues until you have proven (via instruments or some other measure) that this is a critical bottleneck.
That said, creating certain objects can be really expensive, so keeping a cache for certain objects is not in and of itself a bad idea. However, you should never rely on reference counts, even in non-ARC code. Apple docs are very clear about this.
The alternative, as Jacky pointed out is a weak reference. Unfortunately, you can not put a weak reference into standard collections (though, ironically, you can put them in C++ collections and they will be managed correctly).
However, you can create a simple wrapper class to hold a weak reference.
#interface WeakWrapper : NSObject
#property (readonly) id object;
- (id)initWithObject:(id)object;
#end
#implementation WeakWrapper {
__weak id _object;
}
- (id)object {
return _object;
}
- (id)initWithObject:(id)object {
if (self = [super init]) {
_object = object;
}
return self;
}
#end
You can then place these objects inside collections, and then...
WeakWrapper *wrapper = // get the object from the collection
id object = wrapper.object;
if (nil == object) {
// You know the object that was being referenced no longer exists
// so this wrapper can be removed from the collection and destroyed.
}

Need some advice on object oriented design for an iOS project

I have a few questions about code design. This might be long. I'll shorten it whereever possible.
Q1) Dependant or Independant?
Creating a class and adding required functionality so as to allow the object to change its own state vs state being changed by a controller (aka viewcontroller)
I find code examples are best when trying to communicate:
Note: I reduced some lines of code. Original code from http://www.techotopia.com/index.php/An_Overview_of_Objective-C_Object_Oriented_Programming.
Anyways if I had to set the Account balance for an account it is suggesting I do this:
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
#end
// Implementation Section Starts Here
#implementation BankAccount
-(void) setAccountBalance: (double) x
{
accountBalance = x;
}
-(double) getAccountBalance
{
return accountBalance;
}
#end
//usage
BankAccount *account1 = [BankAccount alloc] init];
[account1 setAccountBalance: 1500.53];
----HOWEVER I believe I would have wrote it in a controller like this:------
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
import "BankAccount.h"
#interface MeViewController : UIViewController
-(void)setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc;
#end
#implementation myViewController
-(void) setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc
{
tempBankAcc.accountBalance = x;
}
//USAGE
BankAccount *account1 = [BankAccount alloc] init];
[self setAccountBalance(Account1,1500.53)]
#end
because I believe it is Me (meViewController) setting the AccountBalance, not the account itself as an account is just an account.
Is this a very bad idea? I can see with their example that the object can look after itself (independent) meaning changing its own state whereas my approach says that the BankAccount can only be modified through/with the controller (dependant)
???
Q2) What should/should not be in a controller?
I have also read somewhere that code written inside the controller should be only for:
Responding to user interaction & Updating the views
so does this means I should never do the following in the controllers:
READ or WRITE to and from NSUserDefaults. Since its a singleton, I thought it would be easier to write to it regardless of which controller is currently active? bad idea?
I understand that I should save data (includes NSUserDefaults) in applicationDidEnterBackground and in applicationWillTerminate so does that its a bad idea to save elsewhere (eg. in another controller).
Q3) Which design patterns do you most commonly use and which ones do you abuse wrongly?
Singletons:
My understanding is that [UIApplication sharedApplication],[NSNotification defaultCenter] and other singletons are accessible via all controllers, how about NSObject subclasses? or UIView subclasses?
And apparently you can use NSNotification to notify other controllers when the model has been updated.
Can someone tell me an example of when to use and how to use that?
Maybe when you import some data, that has different attributes, than was originally intended, then the observers could be notified of an upgraded data model, is that an example of when you would within your data model notify a controller?
Thats enough questions for now.
Sorry but I had to get them all out of my head:-)
Ben
First things first: don't use this
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
#end
Here, the accountBalance ivar is public, while it should be private.
Instead, use a #property:
#interface BankAccount: NSObject
#property (assign, nonatomic) double accountBalance;
#end
That'll define a setter:
- (void)setAccountBalance:(double)accountBalance { ... }
and a getter:
- (double)accountBalance { ... }
and a private instance variable (ivar) named _accountBalance.
You can then, in your implementation, use:
#synthesize accountBalance;
which will automatically create the setter/getter like this:
- (void)setAccountBalance:(double)accountBalance {
_accountBalance = accountBalance;
}
- (double)accountBalance {
return _accountBalance;
}
Q1
If you take away all the business logic from the object itself, it's nothing more than a shallow container object. Further more, you need to replicate that logic in every controller you use. Business logic goes into business objects.
To your concrete example, the method of the controller does nothing but delegates the call down to the very object itself (infact, calling the same method if you use properties here). So you gained nothing at all. It may be fine to have that method in the controller, if the controller does more than just calling down on the object, maybe update some more data. One of the good hints here is that the controller does not use any of its own instance variables. It could easily be a class method. It's a code smell.
Q2
Basically, you have three choices for accessing NSUserDefaults: application level, view controller level, or view level.
Worst case is view level - a view should work in any context and should be configurable any way you like, and it certainly should not depend on some magic outside things. This would make reusability (not only for other apps, but also within the same app) a pain.
Accessing the defaults on the view controller level is often ok, especially if they take some singleton role. I.e. if you only ever have one playing screen and one setting screen, each of them might easily talk to the defaults. If there's the chance that you may have several instances of the same class differently configured, this gets a pain and bad smelling work arounds to "individualize" those.
This is where you want to place the access of the defaults outside of the view controllers, which is the most elegant and flexible approcach, but sometimes just not necessary.
Reusability may come earlier than expected, i.e. opening up a second text editor window (which might or might not show a different font), a second settings screen (i.e. a popover), a second playing screen for board games, etc.
Q3
I don't think Singletons are bad per se. They do come with a hefty price tag, though. They come convenient at early stages, just like global variables do.
They get very expensive, soon. There's no ownership, everything is shared, no chance to change a single bit without effecting the other users of that object. Reusability for objects depending on singletons is poor, as you always need those singletons as well. I tend to avoid them most of the time. And whenever I had one of them in my code, getting rid of them was a good decision.
As for the notifications: they are really designed for communicating on a system level. They shouldn't be abused for normal application logic and communication. It's a broadcast for system level events. If you use them as a substitute for object communication, this is a sure way to hell. This takes every logic out of the code, and there's no way build up responsible code.
Q1) Model-layer objects, especially ones that will be interacted with and mutated, should be responsible for their own internal representation as well as representing the knowledge of the rules of the interactions. For a bank account, I think both the approaches you present are wrong. The second in particular because it is actually taking even the responsibility of updating the state away from the account. But the first also because it only provides a setBalance method, which doesn't make sense in the real world. Whoever uses that account has to now handle all the logic of transfers, withdrawals, deposits, interest, and so on. Really, a bank account should have the methods deposit withdraw balance and so on, that way it can represent the rules and logic by which these interactions happen. In this case drawing from how this would work in real life can be helpful.
Q2) A lot of this depends on how your app is set up. A simple app's model layer may be just a plist or NSUserDefaults and some NSDictionary instances. In that case you might not want to have a view controller interact with it, but maybe a data controller object. But you can probably get away with having view controllers talk to that kind of model. When things get more complex though, you definitely need to separate concerns, and have controller objects closer to the data model or have more sophisticated models providing the rules of their interactions. Personally I'd avoid having all the view controllers loading NSUserDefaults, you could just make a single data controller class that could handle that and instantiate it as needed.
Q3) I see two questions here. Not sure what you mean by "accessible to all controllers". But NSNotification is incredibly useful when used right. Say you have 3 view controllers, all coordinating a different view of the bank account - one is a ledger, one is a pie chart, one is a budget calculator. When the app makes a request to refresh the bank account's information from the internet, when that request comes back it can notify all three of these view controllers at once and they can refresh their views accordingly. It's really used any time you have more than one object interested in knowing that something happened.
Hope this helps and let me know if you have any questions.
Read Stanford's lecture about MVC. I think you will find many answers there http://www.stanford.edu/class/cs193p/cgi-bin/drupal/node/205

Creating Objects on the fly in Objective-C

I'd like a critique of the following method I use to create objects:
In the interface file:
MyClass * _anObject;
...
#property (retain, nonatomic) MyClass * anObject;
In the implementation file:
#property anObject = _anObject
so far, so simple. Now let's override the default getter:
(MyClass *) anObject {
if(_anObject == nil) {
self.anObject = [[MyClass alloc] init];
[_anObject dowWhateverInitAction];
}
return _anObject;
}
EDIT:
My original question was about creating the object only (instead of the whole life-cycle), but I'm adding the following so that it doesn't through off anyone:
- (void) dealloc {
self.anObject = nil;
}
/EDIT
The main point of the exercise is that setter is used inside the getter. I've used it for all kind of objects (ViewController, myriad other types, etc.) The advantage I get is:
An object is created only when needed. It makes the app pretty fast
(for example, there are 6-7 views in an app, only one gets created in
the beginning).
I don't have to worry about creating an object before it's used... it happens automatically.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
Questions:
Does it happen to be an established pattern?
Do you see any drawbacks of doing this?
This pattern is quite commonly used as a lazy-loading technique, whereby the object is only created when first requested.
There could be a drawback to this approach if the object being created lazily takes a fair amount of computation to create, and is requested in a time-critical situation (in which case, it doesn't make sense to use this technique). However I would say that this is a reasonable enough thing to do should the object be quick to create.
The only thing wrong with your implementation (assuming you’re not using ARC yet) is that you’ve got a memory leak—using the setter means that your MyClass instance is getting over-retained. You should either release or autorelease _anObject after that initialization, or assign its value directly instead of calling the setter.
Aside from that, this is totally fine, and it’s a good pattern to follow when the MyClass is an object that isn’t necessarily needed right away and can be recreated easily: your response to memory warnings can include a self.anObject = nil to free up the instance’s memory.
It looks like a decent lazy initialization. Philosophically, one can argue that the drawback is that a getter has a side effect. But the side effect is not visible outside and it is kind of an established pattern.
Lazy instantiation is an established pattern, and it is used by Apple in their (terrible) Core Data templates.
The main drawback is that it is overly complex and often unnecessary. I've lost count of the number of times I've seen this where it would make more sense to simply instantiate the objects when the parent object is initialised.
If a simple solution is just as good, go with the simpler solution. Is there are particular reason why you can't instantiate these objects when the parent object is initialised? Perhaps the child objects take up a lot of memory and are only rarely accessed? Does it take a significant amount of time to create the object and you are initialising your parent object in a time-sensitive section of your application? Then feel free to use lazy instantiation. But for the most part, you should prefer the simpler approach.
It's also not thread-safe.
Regarding your advantages:
An object is created only when needed. It makes the app pretty fast (for example, there are 6-7 views in an app, only one gets created in the beginning).
Are you referring to views or view controllers? Your statement doesn't really make sense with views. I don't normally find myself needing to store view controllers in instance variables/properties at all, I instantiate them when I need to switch to them and push them onto the navigation stack, then pop them off when I'm done.
Have you tried your app without using this pattern? Conjecture about performance is often wrong.
I don't have to worry about creating an object before it's used... it happens automatically.
No, now you have to worry about writing a special getter instead. This is more complex and prone to mistakes than simple instantiation. It also makes your application logic and performance more difficult to understand and reason about.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
You don't have to worry about that when you instantiate it during your parent object's initialisation.
Yes this is an established pattern. I often use lazy instantiation like this as an alternative to cluttering up -init or -viewDidLoad with a bunch of setup code. I would assign the value to the instance variable instead of using the synthesized setter in the event that this object ends up being created as a result of something happening in -init.

Resources