Cocoa lazy instantiation - best practice - cocoa

I have a question about the best coding practice for lazy instantiation. 
I have a custom class (MainClass) that consitutes the model of my view controller. One of the properties of MainClass is another custom class (SubClass).
Now let's say I want to acces and set some of the properties of SubClass from my view controller.
Should I lazy instantiate SubClass in MainClass?
Lazy instantiating SubClass in MainClass save me the trouble to check the existence of SubClass (and to create it if it doesn't exist) every time I want to set one of its properties.
On the other hand though I lose the ability to set variables in my views only if SubClass exists. Let me explain better. Let's say I want to set the stringValue of my textfield only if SubClass.name exists. Every time I ask for the existence of SubClass.name the MainClass will lazily instantiate SubClass which is a waste.
What's the best way to proceed?

You need to make up your mind about the aesthetics, if that's what's driving this question, or you need to explain the performance constraints.
Yes, lazy initialization has advantages and disadvantages.
ADVANTAGES
you don't pay for objects you never use
you don't need actually set fields on the object you won't ever use
if you need it, you can build the object at the last minute, which is usually preferable to building it at startup
DISADVANTAGES
(slight) complexity -- especially if you or colleagues aren't accustomed to the idiom
if you forget to call Initialize() or equivalent in an accessor, you may get tricky bugs in some languages, or crashes in others
A hybrid approach is possible. For important tasks, use lazy instantiation:
- (void) display {
[self initialize];
[self display];
}
and for unimportant tasks, simply check for initialization.
- (void) updateCaches {
if ([self isInitialized]) {
[self reloadCachedDataFrom: [self startDatabaseSession]];
}
}
You don't want to build your object just to update its caches, but perhaps, if the object is live, you would like to go ahead and keep the caches warm. So, you see if you've already instantiated the object, and reload the caches only if it already has been set up.

Related

Why use delegate and protocol instead of just passing an instance in Swift?

I was trying to pass around variables between views in Swift, and ran into the rather abstract concept of protocols and delegates.
Then I tried storing a reference to the first view in a second view and call functions on that directly. This seems to work:
SCREEN 1
class Screen1: UIViewController {
var myName = "Screen1"
override func viewDidLoad() {
super.viewDidLoad()
}
//
// checking if the segue to screen 2 is called and then passing a reference
//
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "screen2Segue"{
let vc = segue.destinationViewController as Screen2
vc.storedReference = self
}
}
func getName() -> String {
return myName
}
}
SCREEN 2
class Screen2: UIViewController {
var storedReference:Screen1!
override func viewDidLoad() {
super.viewDidLoad()
}
func testReference() {
// calling a function on the stored reference to screen 1
var str = storedReference.getName()
println("Leaving screen 2, going to " + str)
}
}
My question: what's wrong with this code? Why use delegates and protocols if you can just pass around a reference directly?
Perhaps related: when does a view get un-initialized and replaced by an entirely new view instance? Am I calling 'getName()' on an old instance?
Protocols are useful for separating implementation from interface, which helps increase code reusability, understandability, and testability.
For example, perhaps you wish to store items in a List of some sort. Some possible implementations of a List include array-based implementations and node-based (linked-list) implementations. If you were to declare a protocol called List and have classes ArrayList and LinkedList that implemented that protocol, anything that required the use of a list (variable passed as a parameter to a method, a property, etc) could use List as the variable type, and be able to function without caring about whether a the list was an ArrayList or a LinkedList. You could change which type was used, or how they were implemented, and it would not matter to whatever was using them, because only the exposed interface declared in the protocol would be visible.
Protocols can also be useful for emulating something like multiple inheritance, as a class can inherit from a superclass, as well as implement one or more interfaces. (eg. A bat is both a mammal and winged, so it could be represented as a Bat class inheriting from a Mammal class that implements the Winged protocol).
The delegate pattern uses protocols to delegate some responsibilities to another object, which is especially good for code separation and reusability. For example, the UITableViewDelegate protocol in iOS allows a UITableView to react to things like cell selection by delegating another object to handle the event. This has probably been used by millions of objects in thousands of applications, without the developers at Apple who implemented UITableView and UITableViewDelegate having ever known anything about the objects that were implementing the protocol.
By directly passing a reference between your view controllers, you are forcing the second to be completely dependent upon the first. If you ever wished to change the flow of your application so that the second view controller could be accessed from somewhere else, you would be forced to rewrite that view controller to use the new origin. If you use a protocol instead, no changes to the second view controller would have to be made.
It is a basic design principle to not expose any more of a design than you have to. By passing the reference around you are exposing the whole object. Which means that others can call any of its functions and access any of its properties. And change them. This isn't good. Besides letting others use the object in ways it might not have intended, you will also run into issues if you try to change the object in the future and find out that it breaks somebody else who was using something you didn't intend. So, always a good idea to not expose anything that you don't have to. This is the purpose of delegates and protocols. It gives the object complete control over what is exposed. Much safer. Better design.
I think you didn't fully get the understanding what protocols are.
I always say protocols are like contracts.
The delegate object that implements a certain protocols promises that it can do things the delegator can't do.
In real world I have a problem with my house's tubes.
I (the delegator) call a plumber (the delegate) to fix it. The plumber promises (by contract) to be able to duo it. The promise is the protocol. I don't care how he do it, as long as he does it.
But these contracts are not only useful for delegation.
I am just writing a food ordering app. As it has a menu it need item to display in it.
I could go with basic inheritance and write a class MenuItem, that all sub classes must inherit from.
Or I write an protocol to express: «No matter what object you are, as long as you fulfill this contract we have a deal». this allows me to create many different classes or annotate existing classes in categories, although I don't have the tool of multiple inheritance.
Actually I do both: I write a protocol MenuItem and a class MenuItem that conforms to the protocol. Now I can use simple inheritance or use classes that do not inherit from the class MenuItem.
Code in Objective-C (sorry: I am still transitioning to Swift)
#protocol MenuItem <NSObject>
-(NSString *)name;
-(double) price;
-(UIColor *)itemColor;
#end
#interface MenuItem : NSObject <MenuItem>
#property (nonatomic, copy) NSString *name;
#property (nonatomic, assign) double price;
#property (nonatomic, strong) UIColor *itemColor;
#end
#import "MenuItem.h"
#implementation MenuItem
-(id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if (self) {
self.name = [decoder decodeObjectForKey:#"name"];
self.price = [decoder decodeDoubleForKey:#"price"];
self.itemColor = [decoder decodeObjectForKey:#"itemColor"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.price forKey:#"price"];
[encoder encodeObject:self.name forKey:#"name"];
[encoder encodeObject:self.itemColor forKey:#"itemColor"];
}
#end
Apple uses the same Architecture for NSObject: there is a protocol and a class NSObject. This allows classes, that aren't intact inheriting from the class NSObject to act ash an NSObject. One famous example:NSProxy.
in your case Screen1 promises to be able to understand messages that are send by the detail view controller Screen2. These allows decoupling: any object that does understand Screen1's protocol can be used. Also it helps to maintain a sane object tree, as we don't have to have circular imports. But in general you have to keep in mind that the delegator (Screen2) must keep a weak reference to it's delegate, otherwise we have a retain circle.
Of course an important example it UITableView:
The table view object knows everything about rendering it's cells, handling scrolling and so one. But the engineer who wrote it couldn't now how you want your table view look like. That's why he introduced a delegate to give you the chance to create the right cell. As he couldn't also know what your data looks like, he also introduced the datasource - that works exactly like a delegate: you will be asked to provide all information about your data, that are needed.
This is mostly a matter of opinion so this question should probably be closed, but I think the developer community as a whole is in an agreement on this so I am going to answer it anyway.
An important concept in Software Architecture (the design of the structure of code) is called Separation of Concerns. The basic principle is that you should break down what your code has to do into small components that only have one distinct purpose. Each of these components should be able to stand mostly on their own without much concern with other components other than the ones it needs to directly be interacting with.
This helps greatly with code reuse. If you design a small component that is independent of most / if not all other components, you can easily plug that into other parts of your code or other applications. Take UITableView for example. By using the delegate pattern, every developer can easily create a table view and populate it with whatever data they want. Since that data source is a separate object (with the separate concern of coming up with the data) you can attach that same data source to multiple table views. Think of a contact list on iOS. You will want to access that same data in many ways. Instead of always rewriting a table view that loads the specific data and displays it in a specific way, you can reuse the data source with a different table view as many times as you want.
This also helps with the understandability of your code. It is tough for developers to keep too many thing in their head about the state of your app. If each of your code components are broken down into small, well defined responsibilities, a developer can understand each component separately. They can also look at a component, and make accurate assumptions about what it does without having to look at the specific implementation. This isn't such a big deal with small apps, but as code bases grow, this becomes very important.
By passing in a reference to your first view controller, you are making your second view controller completely dependent on the first. You cannot reuse the second view controller in another instance and its job becomes less clear.
There are lots of other benefits to separation of concerns but I believe those are two compelling and important ones.
I think the problem with the latter arises with multiple reuse of a single class.
Take for example a custom UITableViewCell called CustomTableViewCell. Let's say you have Class A and Class B which both have tableViews and both would want to use CustomTableViewCell as their cell. You now have two options. Would you rather:
A. Use a delegate/protocol for CustomTableViewCell called CustomTableViewCellDelegate. Declare a single object inside the class CustomTableViewCell named "delegate" which implements the mentioned protocol and call on that regardless of what class it calls on
or
B. Declare an object for each class (Class A, Class B) inside CustomTableViewCell so you can hold a reference to each of them.
If you need to use CustomTableViewCell for a number of classes, then I think you know which option to take. Declaring multiple objects for different classes inside CustomTableViewCell would be a pain to see from a software architecture standpoint.

Reverse Cocoa bindings and identify the bindings target view?

I have a custom class that exposes an NSString property. In Interface Builder I've bound the title of an NSButton to the property of my custom class.
Is it possible to get a reference to the NSButton instance from within my custom class?
Essentially I'm trying to locate all the user interface elements that are bound to the property in my custom class.
In general, this sounds like an anti-pattern and/or a bad idea. That said, there are a couple of things to bear in mind. Multiple observers could be bound to your property. You can override addObserver:forKeyPath:options:context: and removeObserver:forKeyPath: (and removeObserver:forKeyPath:context:) and then maintain your own array of observers. With that approach I would caution you that you may need to go to extra effort for the array to not retain observers, as traditionally KV observations don't retain the observing object, and you will likely run into leaks/heap growth if you start retaining them by putting them in an NSArray.
The other gotcha with overriding addObserver:... and removeObserver:... is that, without considerable extra work, you wont know if the observation is for a binding or for something else (like, say, a dependent keyPath notification). One possible workaround for that would be to interrogate the observer via infoForBinding: on all exposedBindings on a later runloop pass using performSelector:afterDelay:. (I think I just threw up in my mouth a little bit for suggesting this.)
Relying on private implementation details of the KVO system is not likely to be a good approach, unless your goal is simply to better understand how KVO works, but it sounds like you're actually trying to accomplish something.
Really, this whole approach just feels like a recipe for disaster. It sounds like an MVC violation from the get-go. Why would the model object need to know about the view objects? Whatever you're trying to accomplish here would almost certainly be better accomplished by having the nib be owned by an NSViewController subclass which has IBOutlets for all the UI elements, and properties for the model. That object would then be in a position to more cleanly manage the apparently complex relationship between your view and model objects without runtime trickery. Since you've not elaborated on the ultimate goal of this trickery, it's hard to say what the best approach would be.

Key-Value Coding and methods calling

It's a question about good programming techniques with Cocoa.
When you want to call a method on one property of your class, should you use KVC to get the receiver or just put the name of your property?
Example, KVC:
[[self property] myMethod];
Example, simple:
[property myMethod];
Thanks!
Example, KVC:
[[self property] myMethod];
That isn't KVC. The KVC way is:
[[self valueForKey:#"myProperty"] myMethod]
There is no reason to do this when you know the property at compile time; you can just ask for the property value or the ivar value directly. With KVO and (on the Mac) Bindings already implemented, there's not much reason to use KVC directly, as KVO and Bindings use it for you.
Example, simple:
[property myMethod];
That doesn't access the property; it accesses the ivar.
You're only accessing the property when you send an accessor message to the property's holder (self in your examples). It doesn't matter whether you use [self property] or self.property, as they're equivalent; either one is a property message to self, with whatever side effects that implies.
That's the key difference: Hitting the accessor may cause side effects, whereas accessing the ivar directly never will.
Hence, the best practice: Use the property in all your instance methods (as you probably want the accessors' side effects), except in init methods and dealloc, where side effects would be a bad thing. (As a general rule, you should not send messages to a half-initialized or half-deallocked object. The exception is when you explicitly commented the method as being part of your init/dealloc process and therefore wrote it to be safe to use in such circumstances.)
I believe the formal version is technically correct as that will guarantee any side-effects from a funky getter. (To make sure, make a custom getter that includes NSLog("in getter!") and let us know if it works.)
For setting you have to use the [self setProperty:foo]; as property = foo bypasses the setter and can lead to memory leaks.
If it feels more natural to you, the dot notation (e.g., self.property and self.property = foo) is identical to [self property] and [self setProperty:foo].

Best practice for copying private instance vars with NSCopying

I might be missing something obvious here, but I'm implementing NSCopying on one of my objects. That object has private instance variables that are not exposed via getters, as they shouldn't be used outside the object.
In my implementation of copyWithZone:, I need alloc/init the new instance, but also set up its state to match the current instance. I can obviously access current private state from inside copyWithZone:, but I can't set it into the new object, because there are no accessors for that state.
Is there a standard way around this while still keeping data privacy intact?
Thanks.
First, you should always have getters, even if they're private. Your object should only access even its own ivars using accessors (except in a very small number of cases). This will save you a great deal of suffering over memory management.
Second, Alex's suggestion of using -> is a standard approach, even though this violates the getters rule above. There are a small number of exceptions to that rule, and copy is one of. Using private setters here is still reasonable (and I used to do it that way exclusively), but I've found for various reasons that using -> often works out cleaner.
Be very careful to get your memory management correct. If you need to call [super copyWithZone:], then you should also read up on the complexities of NSCopyObject() and how it impacts you even if you don't use it yourself. I've discussed this at length in "NSCopyObject() considered harmful."
You can access the instance variables of the copy directly. You use the same pointer dereferencing syntax you would use with a struct. So, for example, if your class is this:
#interface MyCopyableClass : NSObject {
int anInstanceVariable;
}
#end
You can do this:
- (id)copyWithZone:(NSZone *)zone {
MyCopyableClass *theCopy = [[[self class] allocWithZone:zone] init];
theCopy->anInstanceVariable = anInstanceVariable;
return theCopy;
}
One option is to create a custom initializer that accepts the private iVar values. So you create it like:
-(id) initWithPropertyOne:(SomeClass *) anObject andPropertyTwo:(SomeClass *) anotherObject;
When you instantiate the copy, just use the custom initializer.

NSArrayController and KVO

What do I need to do to update a tableView bound to an NSArrayController when a method is called that updates the underlying array? An example might clarify this.
When my application launches, it creates a SubwayTrain. When SubwayTrain is initialised, it creates a single SubwayCar. SubwayCar has a mutable array 'passengers'. When a Subway car is initialised, the passengers array is created, and a couple of People objects are put in (let's say a person with name "ticket collector" and another, named "homeless guy"). These guys are always on the SubwayCar so I create them at initialisation and add them to the passengers array.
During the life of the application people board the car. 'addPassenger' is called on the SubwayCar, with the person passed in as an argument.
I have an NSArrayController bound to subwayTrain.subwayCar.passengers, and at launch my ticket collector and homeless guy show up fine. But when I use [subwayCar addPassenger:], the tableView doesn't update. I have confirmed that the passenger is definitely added to the array, but nothing gets updated in the gui.
What am I likely to be doing wrong? My instinct is that it's KVO related - the array controller doesn't know to update when addPassenger is called (even though addPassenger calls [passengers addObject:]. What could I be getting wrong here - I can post code if it helps.
Thanks to anyone willing to help out.
UPDATE
So, it turns out I can get this to work by changing by addPassenger method from
[seatedPlayers addObject:person];
to
NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers];
[newSeatedPlayers addObject:sp];
[seatedPlayers release];
[self setSeatedPlayers:newSeatedPlayers];
I guess this is because I am using [self setSeatedPlayers]. Is this the right way to do it? It seems awfully cumbersome to copy the array, release the old one, and update the copy (as opposed to just adding to the existing array).
I don't know if its considered a bug, but addObject: (and removeObject:atIndex:) don't generate KVO notifications, which is why the array controller/table view isn't getting updated. To be KVO-compliant, use mutableArrayValueForKey:
Example:
[[self mutableArrayValueForKey:#"seatedPlayers"] addObject:person];
You'll also want to implement insertObject:inSeatedPlayersAtIndex: since the default KVO methods are really slow (they create a whole new array, add the object to that array, and set the original array to the new array -- very inefficient)
- (void)insertObject:(id)object inSeatedPlayerAtIndex:(int)index
{
[seatedPlayers insertObject:object atIndex:index];
}
Note that this method will also be called when the array controller adds objects, so its also a nice hook for thinks like registering an undo operation, etc.
I haven't tried this, so I cannot say it works, but wouldn't you get KVO notifications by calling
insertObject:atArrangedObjectIndex:
on the ArrayController?
So, it turns out I can get this to work by changing by addPassenger method from
[seatedPlayers addObject:person];
to
NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers];
[newSeatedPlayers addObject:sp];
[seatedPlayers release];
[self setSeatedPlayers:newSeatedPlayers];
I guess this is because I am using [self setSeatedPlayers]. Is this the right way to do it?
First off, it's setSeatedPlayers:, with the colon. That's vitally important in Objective-C.
Using your own setters is the correct way to do it, but you're using the incorrect correct way. It works, but you're still writing more code than you need to.
What you should do is implement set accessors, such as addSeatedPlayersObject:. Then, send yourself that message. This makes adding people a short one-liner:
[self addSeatedPlayersObject:person];
And as long as you follow the KVC-compliant accessor formats, you will get KVO notifications for free, just as you do with setSeatedPlayers:.
The advantages of this over setSeatedPlayers: are:
Your code to mutate the set will be shorter.
Because it's shorter, it will be cleaner.
Using specific set-mutation accessors provides the possibility of specific set-mutation KVO notifications, instead of general the-whole-dang-set-changed notifications.
I also prefer this solution over mutableSetValueForKey:, both for brevity and because it's so easy to misspell the key in that string literal. (Uli Kusterer has a macro to cause a warning when that happens, which is useful when you really do need to talk to KVC or KVO itself.)
The key to the magic of Key Value Observing is in Key Value Compliance. You initially were using a method name addObject: which is only associated with the "unordered accessor pattern" and your property was an indexed property (NSMutableArray). When you changed your property to an unordered property (NSMutableSet) it worked. Consider NSArray or NSMutableArray to be indexed properties and NSSet or NSMutableSet to be unordered properties. You really have to read this section carefully to know what is required to make the magic happen... Key-Value-Compliance. There are some 'Required' methods for the different categories even if you don't plan to use them.
Use willChangeValueForKey: and didChangeValueForKey: wrapped around a change of a member when the change does not appear to cause a KVO notification. This comes in handy when you are directly changing an instance variable.
Use willChangeValueForKey:withSetMutation:usingObjects: and didChangeValueForKey:withSetMutation:usingObjects: wrapped around a change of contents of a collection when the change does not appear to cause a KVO notification.
Use [seatedPlayers setByAddingObject:sp] to make things shorter and to avoid needlessly allocating mutable set.
Overall, I'd do either this:
[self willChangeValueForKey:#"seatedPlayers"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:sp];
[seatedPlayers addObject:sp];
[self didChangeValueForKey:#"seatedPlayers"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:sp];
or this:
[self setSeatedPlayers:[seatedPlayers setByAddingObject:sp]];
with the latter alternative causing an automatic invocation of the functions listed under 1. First alternative should be better performing.

Resources