what is the exact meaning of delegate in iphone?how it is implemented in UIViewController?
A delegate is an object that usually reacts to some event in another object and/or can affect how another object behaves. The objects work together for the greater good of completing a task. Typically a delegate object will be shared by many other objects that have a more specific task to carry out. The delegate itself will be more abstract and should be very reusable for different tasks. The object which contains the delegate typically sends the delegate a message when a triggered event occurs, giving the delegate an opportunity to carry out its specified task.
There's more documentation here that you should read to understand the delegate pattern in Cocoa and Cocoa touch, particularly with how delegation is used between UIWindow and UIView. It is an integral design pattern in iPhone architecture and one that should be mastered if you wish to design a clean application.
Delegates are used to delegate tasks of objects to their owner (or any object, really). A good reason for this is it makes it easier to use composition instead of inheritance. Delegates are a reference to an object that conform to a specified protocol so you can guarantee it will implement the required methods. A good example is UIApplicationDelegate. Notice how the delegated methods (from the protocol) use verbs that applicationDid, applicationShould, applicationWill etc. Usually delegate methods either ask for permission to do something (and choose to do it this way, in a method, rather than with just a BOOL property, for more flexibility) or notify the delegate of an event that will happen or did happen.
Delegation is a pattern and the term means the same in Cocoa.
A delegate is not implemented in a UIViewController. Different kinds of view controllers are assigned a delegate to handle certain tasks. One of the best examples (if we're talking iPhone) is the UITableViewDelegate, which is called to do certain things when certain table-related events occur.
A delegate is used to communicate/pass data b/w two objects of a class/struct to complete a task.
For example: Consider firstVC(sender or Delegator or CEO) which sends confidential data to secondVC(receiver or Delegate or Secretary).
This is done by making secondVC conforming to a
protocol passDataDelegate { func passdata(data: String) }
class secondVC : UIViewController, passDataDelegate {
func passdata(data: String) {
print("CEO passed //(data)")
}
}
class firstVC : UIViewController {
var delegate : passDataDelegate?
}
Now create objects of both firstVC & secondVC
let sender = firstVC()
let receiver = secondVC()
Since, receiver conforms to protocol passDataDelegate. So, it is having type either as UIViewController or passDataDelegate because if a class conforms to a protocol then the object of its class can have protocol as type.
Hence, assign sender.delegate = receiver
Now, we can CEO(sender) can pass data to Secretary(receiver) through its delegate property as
sender.delegate?.passdata("Confidential data")
Output: CEO passed Confidential data
Now the Secretary(receiver) can use that data to complete her further task.
The concept of delegation is very common in iOS. An object will often rely on another object to help it out with certain tasks. This separation of concerns keeps the system simple as each object does only what it is good at and lets other objects take care of the rest. The table view offers a great example of this.
Related
I have read some posts like this one about the difference between subclassing NSObject in Swift or just having its native base class with no subclassing. But they all are a bit old posts, and I am not clear about this topic.
When should you subclass NSObject? What is the actual difference between subclassing it and not subclassing? What is currently the recommendation in Swift?
Apple's documentation about NSObject states the following as an introduction:
NSObject is the root class of most Objective-C class hierarchies. Through NSObject, objects inherit a basic interface to the runtime system and the ability to behave as Objective-C objects.
As this would suggest, you need to subclass NSObject for types introduced in your code whenever instances of that type need to behave like an Objective-C object (or the class itself, in some rarer cases).
I am not aware of super explicit Apple provided written guidance on when not to subclass NSObject, beyond suggesting reducing dynamic dispatch or presenting code reuse paradigms using that do not relying on subclassing but protocol extensions, i.e. code reuse that is generally more static dispatch and value type friendly). I believe it is fair to say though that most Swift programmers have taken hints from Apple, and Swift language features as signs to avoid introducing NSObject based types when the above-mentioned need is not there. That is, as a general rule, only introduce NSObject based types when you actually need the Objective-C dynamism, most commonly when you need to interface with Cocoa APIs (especially common when your code is UI related: e.g. view controllers, views).
As pointed out in an answer to the question you link to, with Objective-C style dynamism comes the performance of objc_msgSend based method dispatch. Although methods in Swift classes are also virtual, the compiler is able to use faster means of dispatching methods when you don't explicitly mark the methods with the #objc attribute – especially when Whole Module Optimization is toggled on, and even more so in Swift 3 where classes are not by default open for subclassing beyond the module that defines the type.
Beyond avoiding NSObject, you can also avoid class based reference types altogether in many cases when writing Swift. Take a look at for instance the value type WWDC videos linked above, or for example this blog post as an introduction. Briefly, using value types you gain good local reasoning, often avoid dynamic memory allocation and reference counting overhead (though not universally so – structs with reference types as fields being the caveat).
One reason to subclass NSObject is if you need to save some data. NSObject and all it entails remains (AFAIK) the simplest way to get to NSCoding which you need to write to a file.
some insights can be found here or here
Another case when you must subclass NSObject is when you want your subclass to be an observer for KVO, i.e.
addObserver(_ observer: NSObject, forKeyPath keyPath: String, options: NSKeyValueObservingOptions = [], context: UnsafeMutableRawPointer?)
requires the observer to be an NSObject (or an array or set).
Specifically, how does Swift memory management work with optionals using the delegate pattern?
Being accustomed to writing the delegate pattern in Objective-C, my instinct is to make the delegate weak. For example, in Objective-C:
#property (weak) id<FooDelegate> delegate;
However, doing this in Swift isn't so straight-forward.
If we have just a normal looking protocol:
protocol FooDelegate {
func doStuff()
}
We cannot declare variables of this type as weak:
weak var delegate: FooDelegate?
Produces the error:
'weak' cannot be applied to non-class type 'FooDelegate'
So we either don't use the keyword weak, which allows us to use structs and enums as delegates, or we change our protocol to the following:
protocol FooDelegate: class {
func doStuff()
}
Which allows us to use weak, but does not allow us to use structs or enums.
If I don't make my protocol a class protocol, and therefore do not use weak for my variable, I'm creating a retain cycle, correct?
Is there any imaginable reason why any protocol intended to be used as a delegate protocol shouldn't be a class protocol so that variables of this type can be weak?
I primarily ask, because in the delegation section of the Apple official documentation on Swift protocols, they provide an example of a non-class protocol and a non-weak variable used as the delegate to their class:
protocol DiceGameDelegate {
func gameDidStart(game: DiceGame)
func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
func gameDidEnd(game: DiceGame)
}
class SnakesAndLadders: DiceGame {
let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [Int]
init() {
board = [Int](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
}
var delegate: DiceGameDelegate?
func play() {
square = 0
delegate?.gameDidStart(self)
gameLoop: while square != finalSquare {
let diceRoll = dice.roll()
delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare > finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square]
}
}
delegate?.gameDidEnd(self)
}
}
Should we take this as a hint that Apple thinks we should be using structs as delegates? Or is this simply a bad example, and realistically, delegate protocols should be declared as class-only protocols so that the delegated object can hold a weak reference to its delegate?
Should we take this as a hint that Apple thinks we should be using structs as delegates? Or is this simply a bad example, and realistically, delegate protocols should be declared as class-only protocols so that the delegated object can hold a weak reference to its delegate?
Here's the thing. In real life Cocoa programming, the delegate is likely to be an existing class. It is a class because it exists for some other purpose that only a class can satisfy - because Cocoa demands it.
For example, very often, to take iOS as an example, one view controller needs to act as another view controller's delegate for purposes of arranging a message back and forth between them. Ownership of the view controllers is dictated by the view controller hierarchy and by nothing else. So, in Swift, just as in Objective-C, you had better make that delegate property weak, because it would be terrible if one view controller suddenly took memory management ownership of another view controller!
So, in the real world of the Cocoa framework, there is serious danger of incorrect ownership or of a retain cycle. And that is the problem that weak solves. But it only works, as you rightly say, with classes.
The example in the book, however, is about some objects living off in an abstract made-up artificial Swift-only world. In that world, as long as you aren't in danger of circularity (retain cycle), there's no reason not to use structs and there's no reason to worry about memory management. But that world is not the world you will usually be programming in! And that world is not the framework Cocoa world that your Objective-C delegate pattern comes from and belongs to.
Yes, this example is a bit of an oddity.
Because the example uses a non-class protocol type, it has to expect a possible struct implementing the protocol, which means that the DiceGame instance owns its delegate. And indeed, that violates typical assumptions about the delegate pattern.
It doesn't lead to a reference cycle in this case because the DiceGameTracker is a fictional object that doesn't own the DiceGame itself — but in a real-world app it's possible, even likely, that a delegate might also be the owner of the delegating object. (For example, a view controller might own the DiceGame, and implement DiceGameDelegate so it can update its UI in response to game events.)
That kind of reference cycle would probably turn into a confusing mess if either the game, its delegate, or the type implementing one or both of those protocols were a value type — because value types are copied, some of the variables in your setup would end up being distinct copies of the game (or game's owner).
Realistically one would expect to use reference types (classes) to implement this anyway, even if the protocol declaration leaves open the possibility of doing it otherwise. Even in a hypothetical Swift-only world, it probably makes sense to do it that way... generally whenever you have something with long life, internal mutable state, and a usage pattern that has it being accessed by potentially multiple other actors, you want a class type, even if you can sort of fake otherwise with value types and var.
If you must have structs and emums in your protocol, then if you make your delegate nil just before you close the view controller, then this breaks the retain cycle. I verified this in Allocations in Instruments.
// view controller about to close
objectCreatedByMe.delegate = nil
It's an optional, so this is valid.
I've defined two classes in an m file, the first subclassing UIView and the second UIViewController. The UIViewController is instantiated at some point, and the vc is who instantiates my first class.
the first class implements the touchesEnded method, to simulate a button. when the touchesEnded method is fired in the first class, is it possible to easily call a method defined in the 2nd class, without going into delegates and such?
I tried playing with selectors with no luck
is it possible to easily call a method defined in the 2nd class
Yes, assuming that you are creating an instance of the second class and calling the method on that instance.
Regardless of whether the two classes are subclasses of the same type, or in the same or different files, you need a reference to an instance of that class to call a method on it, or force it to perform a selector.
The proper OO way to do this is with delegates, but you could theoretically do something like pass a reference to view 2 into view 1 when you create the views. If you create them in IB you could create outlets so they reference each other that way.
In short: Yes, it is possible and easy to do, but I can't give you too much in terms of specific code without a more specific example of your situation
I am writing an iPhone application which in numerous places needs to perform non HTTP or FTP networking of a very simple request response type.
I've wrapped all this up into a SimpleQuery class that integrates with the run loop.
SimpleQuery *lookup = [[SimpleQuery alloc] init];
[lookup setDelegate:self];
[lookup doQueryToHost:queryServer port:queryPort query:queryString ];
As you can see the calling object sets itself as a delegate. When the results are complete it then calls a method on the delegate with the results.
[delegate simpleQueryResult:resultString simpleQuery:self];
I am now in a position where I have a user of SimpleQuery that has two types of query so I need to extend SimpleQuery to support this.
I can think of two sensible ways of doing this.
Firstly passing a selector into doQueryString, or a seperate doQueryStringWithSelector.
[lookup doQueryToHost:queryServer port:queryPort query:queryString selector:#SEL ];
Secondly passing a tag into doQueryString so that when the delegate is called it can query the tag, as the simpleQuery is passed, to find out what the results are for.
[lookup doQueryToHost:queryServer port:queryPort query:queryString withTag:tag ];
I'm just wondering which is best from a coding style perspective, the first seems simpler but tagging seems more in keeping with the iPhone SDK and Interface Builder
An option which is used commonly in Apple's code (for example, in UIControl) is to provide both a target object and a selector. This works only if there is a single callback, and is more appropriate than a delegate in that case. (If there are multiple callbacks, then you'll probably have to go with a delegate and the tag approach.)
If you go this route, then you do away with the delegate altogether and instead have a method with a signature like this:
doQueryToHost:(id)queryServer port:(int)queryPort query:(NSString*)queryString target:(id)target action:(SEL)action
Note that "action" is typically preferred over "selector" in methods arguments in this case. The query would simply call the selector on the target when done. This would allow your clients to have multiple selectors, and also multiple target objects; this can help clean up code because you don't need to shove everything into a single delegate object.
If you want to go with your tag route, you should call it "context", which is what Apple uses (for example, in addObserver:forKeyPath:options:context).
There's a third option that's a common pattern in the kits, which is to use #protocols.
For example:
#protocol QueryCompleteHandlerProtocol
- (void)queryType1Complete:(int)intStuff;
- (void)queryType2Complete:(float)floatStuff;
#end
What this does is declare a set of method calls that an object adopting the protocol has to conform to (the compiler will actually enforce this).
So your SimpleQuery object will hold on to something like the delegate pointer, which you might declare like this among the ivars:
NSObject<QueryCompleteHandlerProtocol> *callback;
What this tells the compiler is that callback is an object that descends from NSObject and adopts the QueryCompleteHandlerProtocol protocol. Sometimes you see this written as:
id<QueryCompleteHandlerProtocol> callback;
When you want to call the callback there's nothing special about them, SimpleQuery's methods will just call:
[callback queryType1Complete:1];
[callback queryType2Complete:2.0];
Finally you client for the procotol class will declare itself as adopting the protocol:
#interface MyClass : NSObject<QueryCompleteHandlerProtocol>
...
#end
And will set itself as the callback with some code like:
[lookup setCallback:self];
This is where the compiler checks that MyClass conforms to QueryCompleteHandlerProtocol, meaning it has implemented queryType1Complete: and queryType2Complete:.
I'm not sure I understand the problem here. Can't SimpleQuery's user just set another delegate object for the second query, or branch on the simpleQuery: parameter? That's a basic part of the delegate pattern, just like having two UIActionSheets for one view controller.
I'm looking for a reliable design for handling assignments that have asynchronous requests involved. To further clarify, I have a class which handles Data Management. It is a singleton and contains a lot of top level data for me which is used throughout my iPhone application.
A view controller might do something such as the following:
users = [MySingleton sharedInstance].users;
MySingleton will then override the synthesized users getter and see if it is set. If it is not set, it will speak to a Connection Manager (a wrapper for NSURLConnection and its delegate methods) which fires off an asynchronous request, and this is where problems begin. I cannot guarantee when "users" will be available. I could change the request to synchronous, but that will directly effect user experience, especially in a mobile environment where bandwidth is limited already.
I need to be able to at some point, have some kind of locking/synchronization code going on in my getter that doesn't return users until it is available or is nil.
Once the NSURLConnection has the data available, it needs to callback something/somewhere with a response object and let the getter know the data is available.. whether it's failed or succeeded.
Any suggestions on handling this?
I solved this problem a couple ways in different apps.
One solution is to pass an object and selector along to notify such as:
- (id)getUsersAndNotifyObject:(id)object selector:(SEL)selector
This breaks the nice property behavior however. If you want to keep the methods as properties, have them return immediately, with either cached data or nil. If you need to go out to the network, do so asynchronous and then let the rest of the app know the data changed via KVO or the NSNotificationCenter. (Cocoa Bindings would be an option on the Mac, but they don't exist on iPhone).
The two methods are fairly similar. Register for updates with your shared instance, and then ask for the data. KVO is a little lighter weight if you just dealing with raw observable properties, but an NSNotification might be more convenient if you're interested in several different pieces of data.
With an NSNotification, the client object could register for one type of notification which includes the changed data in its userInfo dictionary instead of having to register obvservers for every single key path you're interested in.
An NSNotification would also allow you to pass back failures or other status information a lot more easily than straight KVO.
KVO method:
// register observer first so you don't miss an update
[[MySingleton sharedInstance] addObserver:self
forKeyPath:#"users"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:&kvo_users_context];
users = [MySingleton sharedInstance].users;
// implement appropriate observeValueForKeyPath:ofObject:change:context: method
NSNotification Method:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sharedDataChanged:)
name:MySingletonDataUpdatedNotification
object:[MySingletonDataUpdatedNotification sharedInstance]];
users = [MySingleton sharedInstance].users;
// implement appropriate sharedDataChanged: method
You can either use a delegate pattern or a notification pattern here.
A delegate would let a particular object know when users is complete, a notification pattern would notify any object that wants to know. Both are valid, depending on your situation.
Just remember: if you have any race issues in your app, your architecture is probably all wrong.
It took me a while to realize what the best way of handling this kind of typical task; it turns out the clue is in the design of many of Cocoa and CocoaTouch's own APIs: delegation.
The reason so many of Cocoa's APIs use delegation is because it fits very well with the asynchronous nature of many GUI apps.
It seems perfectly normal to want do do something along the lines of:
users = [MyDataFactory getUsers];
Except, as you point out, you have no idea when the getUsers method will finish. Now, there are some light-weight solutions to this; amrox mentioned a few in his post above (personally I'd say notifications aren't such a good fit but the object:selector: pattern is reasonable), but if you are doing this kind of thing a lot the delegation pattern tends to yield a more elegant solution.
I'll try to explain by way of an example of how I do things in my application.
Let's say we have a domain class, Recipe. Recipes are fetched from a web service. I typically have a series of repository classes, one for each entity in my model. A repository class' responsibility is to fetch the data required for the entity (or a collection of them), use that data to construct the objects, and then pass those objects onto something else to make use of them (typically a controller or data source).
My RecipeRepository interface might look something like this:
#interface RecipeRepository {}
- (void)initWithDelegate:(id)aDelegate;
- (void)findAllRecipes;
- (void)findRecipeById:(NSUInteger)anId;
#end
I'd then define a protocol for my delegate; now, this can be done as an informal or formal protocol, there are pros and cons of each approach that aren't relevant to this answer. I'll go with a formal approach:
#protocol RepositoryDelegateProtocol
- (void)repository:(id)repository didRetrieveEntityCollection:(NSArray *)collection;
- (void)repository:(id)repository didRetrieveEntity:(id)entity;
#end
You'll notice I've gone for a generic approach; you will likely have multiple XXXRepository classes in your app and each will use the same protocol (you may also choose to extract a base EntityRepository class that encapsulates some common logic).
Now, to use this in a controller, for example, where you previous would have done something such as:
- (void)viewDidLoad
{
self.users = [MySingleton getUsers];
[self.view setNeedsDisplay];
}
You would do something like this:
- (void)viewDidLoad
{
if(self.repository == nil) { // just some simple lazy loading, we only need one repository instance
self.repository = [[[RecipeRepository alloc] initWithDelegate:self] autorelease];
}
[self.repository findAllRecipes];
}
- (void)repository:(id)repository didRetrieveEntityCollection:(NSArray *)collection;
{
self.users = collection;
[self.view setNeedsDisplay];
}
You could even extend this further to display some kind of "loading" notice with an additional delegate method:
#protocol RepositoryDelegateProtocol
- (void)repositoryWillLoadEntities:(id)repository;
#end
// in your controller
- (void)repositoryWillLoadEntities:(id)repository;
{
[self showLoadingView]; // etc.
}
Another thing about this design is that your repository classes really don't need to be singletons - they can be instantiated wherever you need them. They may deal with some kind of singleton connection manager but at this layer of abstraction a singleton is unnecessary (and its always good to avoid singletons where possible).
There is a downside to this approach; you may find you need layers of delegation at each level. For instance, your repositories may interact with some kind of connection object which does the actual asynchronous data loading; the repository might interact with the connection object using it's own delegation protocol.
As a result you might find you have to "bubble up" these delegation events throughout the different layers of your application using delegates that get more and more coarse-grained as they get closer to your application-level code. This can create a layer of indirection that can make your code harder to follow.
Anyway, this is my first answer on SO, I hope its been helpful.