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.
Related
Each view class has multiple init methods - ones already included as part of UIView, and then additional ones - and each of them set up the same elements in the same way. I therefore usually have them all running a [self initialSetup]; method, which includes the setting up of all of these elements.
The problem i've ran into is that if a subclass also has an initialSetup method, it would override the superclass initialSetup method, and thus the superclass would have to have the method be public in order to still function. This causes problems with organisation, as the method should never be called other than from init, so has no reason to be public.
You've hit upon a problem that there's no perfect fix for. What you'd ideally have is a method that can't be subclassed in the normal sense, that's accessible only to instances of that exact type of class.
Where this is a risk, the normal practice seems to be to incorporate the class name into the setup method. So instead of initialSetup you'd have something like myViewSubclassInitialSetup.
You can also add something like this at the top of your method:
NSAssert([self isMemberOfClass:[ThisClass class]],
#"IniitalSetup called by sub- or superclass")
Then your debug builds will raise an exception if a subclass or superclass ends up calling your init method. That'll give you a place for a breakpoint and a stacktrace that should allow you to find the problem very quickly.
It won't add any code to your release builds.
Change the name of initialSetup to something like initialSetupClassName - subclasses, even if they accidentally used the same pattern, would not use the same name as they had a different class name.
You can also use an "_" prefix for private methods you would rather not be called, but the subclasser may do that also.
It sounds like you are missing a designated initializer. Designate one initializer as the official one that actually performs the setup, and have all the others just call that with some degree of customization. Usually the designated initializer will be the one with the most detail — for example, if you have init, initWithName:, initWithName:age: and initAsFiveYearOldNamed:, the designated initializer will be initWithName:age: and the other initializers would just call that method with the arguments filled in appropriately.
Unfortunatly Objective C doesn't provide a way to achieve that in a "clean" way. The ideal solution would be a protected method. But that's not possible in Objective C
Apple had this problem, when they were creating the UIGestureRecognizer. There were some methods they really didn't want to get called by somebody, but which had to be overwritten by subclasses. The way they chose to deal with this, was to create a seperate header file (UIGestureRecognizerSubclass.h), that contains a category to the original UIGestureRecognizer with those "protected" methods. The additional header is only to be imported by subclasses (i.e. for subclassing purposes). See UIGestureRecognizer Class Reference for some details.
Of course that doesn't prevent anybody from misusing the additional header file, but at least it clearly states your intention and keeps your code well structured. Also you won't be "bothered" by autocompletion for the additional methods, when just using the class.
Personally I only use an additional header, if it is extremely important that nobody calls it directly. In most cases I think it's ok to use public methods and make a note for what it's inteded. The iOS Framework also has many of these cases. F.e. many methods of UIViewController's viewDidLoad etc.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Using -performSelector: vs. just calling the method
I can accomplish the same task in my application by doing:
[self performSelector:#selector(displayOneLife)];
and:
[self displayOneLife];
Is it better to use one or the other depending on the situation? If so, can someone elaborate for me? I would just like to use Objective-C best practices.
Thank you,
Joey
The -performSelector approach is usually used when you would like to invoke some selector not known at compilation time. For instance, UIButton uses it to invoke the action you wire it up to when a user hits it (the button knows the name of the method it is hooked up in IB and the class it it hooked up to).
For all other cases you should go with the latter as you don't want to convert your code into an unreadable puzzle.
P.S. -performSelector + dynamic selector name construction can be used to work around Apple's static analyzer which seeks the binary for prohibited invocations :)
You can store a selector in a variable, so performSelector: is useful for when you don't know at compile-time what message you want to send. For example, the target-action system is based on selectors. Here's a rudimentary implementation of a control:
#interface FakeControl : NSObject
#property(nonatomic, strong) id target;
#property(nonatomic, assign) SEL action;
- (void)click;
#end
#implementation FakeControl
- (void)click {
[target performSelector:action];
}
#end
By using a selector, we can have the control send any message we want at runtime when it's clicked.
#selector has a very specific use, and you should not use it to call known methods.
You use #selector to inform other classes of one of your methods that should be called.
For example you can pass the class countNumber a selector to your method #selector(result:) so that the other class will call your method when it has completed its task.
example code:
- (void)calculateANumber
{
[NumbersClass countNumber:myNumber withResult:#selector(result:)];
}
//This method will get called by NumbersClass, even tho it didnt know its existence before
- (void)result:(int)countResult
{
myResult = countResult;
}
Just an example, obviously, it does nothing
If you have to do some thing inline especially on the same thread
[self displayOneLife]
is good enough
But there are many instances, where you want to do the execution on another thread, or after a delay etc. If you just type, [self perform ...], you will see so many suggestions for methods available for performSelector, each of the method signatures will help you understand what it does.
Select one of the methods and just command click on the method name. It will show you details about what the method does etc.
It is a very good question but has many answers. Runloops, threads, delays, asynchronous operations are all reasons.
I'm able to make the method for the call [self weaponAttachments:mpk5] but I don't like having to call self. I think [mpk5 weaponAttachments] is more natural and is easier to read.
The problem I'm having is I need to pass in the weapon (mpk5) in order to use it, which I can do with the first method but not with the second one. Does this mean that I need to subclass NSDictionary in order to be able to use a statement like [mpk5 weaponAttachments]? If so, how do I get ahold of the caller "mpk5" so that I can use it inside the method?
EDIT
I apologize for not putting this in the first time but my objective is to have [mpk5 weaponAttachments] return an NSDictionary or NSArray. Right now I have NSDictionary *attachments = [self weaponAttachments:mpk5]; which works but it just doesn't seem like the best approach.
So firstly, your two calls are a little mixed up:
[self weaponAttachments:mpk5] calls the weaponAttachments method, passing in the variable mpk5.
But [mpk5 weaponAttachments] is either asking the mpk5 object to return the weaponAttachments property or is asking the mpk5 object to run a method called weaponAttachments (I'm simplifying here - it's always a method, but if you're using properties you probably won't realise this as Objective-C will create them for you).
These are fundamentally different things.
On to the brunt of your question:
I don't like having to call self
...unfortunately, if you're working in an object-oriented language you're going to have to get used to this. Say I have a class called mySimpleClass, and a method inside that class called doSomething. Writing this:
[mySimpleClass doSomething] would be what we call a static method. Whereas calling [self doSomething] from within an instance of mySimpleClass would be an instance method.
If you're unsure of the difference between static and instance methods you should probably step back and take a look at some of the basic guides out there.
I'm trying to transform one method call into another dynamically (at runtime).
For instance, I'd like the following:
[obj foo]
to delegate to:
[obj getAttribute: #"foo"]
(I'd like to do this dynamically as I don't know ahead of time what those method names or attributes are going to be).
I see that there's a hook into:
- (id) forwardingTargetForSelector: (SEL) aSelector
That only seems to work for delegation, though, I want to keep the object as "self" and transform the method arguments.
Where should I look for this sort of behavior? Is it even possible in obj-c?
You can use the method -forwardInvocation: for that. It takes a full NSInvocation object which represents the method call, and you can handle it however you wish. If you do this, you should also override -methodSignatureForSelector: to return the correct NSMethodSignature (required for -forwardInvocation: to work on unknown selectors). It's also recommended that you override -respondsToSelector: to declare that you can handle the selector in question.
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.