Add run-time information to CocoaHTTPServer using custom Response class - objective-c

I have the following code to start my own Cocoa HTTP Server. In order to manually handle the responses I have created my custom HTTPConnection class named PictureHTTPConnection
self.httpServer = [[HTTPServer alloc]init];
self.httpServer.type = #"_http._tcp.";
self.httpServer.name = #"MyBonjour Name";
self.httpServer.connectionClass = [PictureHTTPConnection class];
The problem here is that the PictureHTTPConnection class needs some information in order to handle the HTTP connections. However, I only provide the class and therefore I don't have a reference to the instance. I could do something with global data but this is not very good programming practise.
The best way I can think of is setting the PictureHTTPConnection's delegate to the UIApplicationDelegate so that it can answer any callbacks. :-(

I had the same exact problem. To solve this, I changed the code of the HTTPServer class so that you can set it a delegate that will in turn be set on each HTTPConnection created. When the HTTPConnection has to handle the request I call the delegate. This is far from clean as well and I was seeking for a better solution.

You can get callbacks by adding a category to HTTPServer that gets & sets a delegate. objc_setAssociatedObject is your friend here:
#interface HTTPServer (WithDelegate)
#property (strong, nonatomic) id delegate;
#end
#implementation HTTPServer (WithDelegate)
NSString const *key = #"HttpServer.WithDelegate.key";
- (void)setDelegate:(id)delegate
{
objc_setAssociatedObject(self, &key, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)delegate
{
return objc_getAssociatedObject(self, &key);
}
#end
Set the delegate when you initialize the HTTPServer instance (or whenever). Call methods on it from your custom HTTPConnection implementation like this:
[config.server.delegate handleRequest:theRequest];
You must implement handleRequest:(Whatever*)theRequest in your delegate class

Related

Objective-C: Where to initialize a delegate

I don´t fully understand how to use the Delegation pattern in obj-C. Basically I have a class: DigGameControlLayer.h and in it´s header I define a protocol with one required method that all users of this class needs to implement. Then I create the delegate property that I use within the code like any other property to delegate responsibility of what the moveObjectToPosition: method should do. So far so good I hope.
//DigGameControlLayer.h
#protocol DigGameControlLayerDelegate <NSObject>
-(void) moveObjectToNewPosition: (CCSprite *)object atSpeed:(float)moveSpeed;
#end
#property (assign) id <DigGameControlLayerDelegate> delegate;
Then the class that is using that class (in this case DigCharacter) says it adheres to the DigGameControlDelegate protocol
#interface DigGoblinPlayer : DigCharacter <DigGameControlLayerDelegate>
But what I don´t understand is where do i Initialize and set the delegate property a declared? Cause currently it does nothing when I use it in DigGameControlLayer since it´s null
[self.delegate moveObjectToNewPosition:object atSpeed:moveSpeed];
You can pass the delegate in the init method like so:
DigGoblinPlayer* player;
player = [[DigGoblinPlayer alloc] initWithName:(NSString*)name delegate:self];
Or set it separately:
DigGoblinPlayer* player;
player = [[DigGoblinPlayer alloc] initWithName:(NSString*)name];
player.delegate = self;
Which style you choose depends on if you always want/need a delegate, or if you want to be able to change/reset it later on.
In some cases you don't want the delegate to be a public property; then you'd use the first style.
You see a lot of example of this in the iOS SDK like here.
Note that self --which is just an example, and could an other object of course-- needs to implement this delegate. And name is something I made up.
in DigGoblinPlayer
implement the method
-(void) moveObjectToNewPosition: (CCSprite *)object atSpeed:(float)moveSpeed
{
}
this method will be called when the method calls in DigGameControlLayer
[self.delegate moveObjectToNewPosition:object atSpeed:moveSpeed];

Update UILabel text from another class in Objective-C

I have a method implemented in the ViewCotroller class to set the message to a UILable in that class.
-(void)setAuthenticationMessage:(NSString *)message{
//lblStatus is the UILabel
lblStatus.text = message;
}
I'm accessing this method from another class to set the message. Though code executes correctly this message didn't update. I tried it by executing this method in a different thread. But that was also unsuccessful. Can anyone help me to figure out the issue?
What are lblStatus's memory management properties? Your naming convention alone leads me to believe that it is something to do with this. Usually you refer to instance variables as:
_lblStatus or self.lblStatus
use #protocol & delegates to access another class refer this link example example2
Use the delegate design pattern (google it). Example:
//In the updating class .h
#protocol LabelChangerDelegate <NSObject>
-(void)handleLabelChangeMessage;
#end
#property (assign, nonatomic) id <LabelChangerDelegate> delegate;
//In the updating class .m
-(void)changeLabelInOtherClass{
if (self.delegate != nil && [self.delegate respondsToSelector:#selector(handleLabelChangeMessage)]) {
[self.delegate performSelector:#selector(handleLabelChangeMessage)];
}
} else {
NSLog(#"Delgate doesn't implement handleLabelChangeMessage");
}
//In the view controller .h
<LabelChangerDelegate>
-(void)viewDidLoad{
//set the delegate to self
}
//In the view controller .m
-(void)handleLabelChangeMessage{
self.label.text=#"I changed through delegation";
}
Another option is to use NSNotificationCenter

Dropbox Delegate methods not being called

I have a problem with the Dropbox API. I'm working on big app, which was started by another developer. Now I'm going to clean the code. All the Delegate Methods (loadedMetadata & Co.) were directly in the view. Now I want to extract them into their own class. So I created a DropboxService class with all the methods in it. So I have the view and call the method loadMetadata from the DropboxService. The method is called and woking fine. But the Delegate method loadedMetadata is never called.
What did I do wrong / what do I have to change to get this working correctly?
The Dropbox Service has the DBRestClientDelegate as a "Superclass" (don't know how it i exactly called)
#interface DropboxService : CloudProviderService <DBRestClientDelegate> {
}
Edit:
The Service is instantiated in the AppDelegate and is a variable there:
- (DropboxService *)getDropboxService {
if (self.dropboxService == nil) {
self.dropboxService = [[DropboxService alloc] init];
}
return self.dropboxService;
}
Greetings from Germany
Alexander
You need to also set the delegate after init
DBRestClient.delegate = self;
from this interface
#interface DBRestClient : NSObject { ... id<DBRestClientDelegate> delegate;
That header doesnt say that DropboxService is a sub-class of DBRestClientDelegate
it says that DropboxService conforms to the protocol of DBRestClientDelegate
The Dropbox sample project explains all this, but you want to look for where you set up DBRestClient and make sure DropboxService is made the delegate of that instance.
This is what it looks like in my code which conforms to DBRestClientDelegate
- (DBRestClient*)restClient {
if (restClient == nil) {
restClient = [((DBRestClient *)[DBRestClient alloc]) initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
}
return restClient;
}

Delegates query in Objective - C

So, I have a decent idea of what a delegate does, why use it, how to implement it etc. and I'm working on implementing it in one of my projects. The problem I'm trying to solve is to decouple my Controller objects from my Network Access class. In this context, the ideas get a little messy in my head.
I somehow intuitively feel that the NetworkAccessClass should be the delegate for a Controller object, because the NetworkAccessClass is acting as a helper for the Controller object. But it seems to work in a reverse fashion, because the following is apparently the right way to do it:
NetworkaccessClass.h
#protocol NetworkAccessDelegate
-(void) requestSucceded:(NSData *) data
-(void) requestFailed:(int) responseCode;
#end
#interface NetworkAccessClass : NSObject
{
id<NetworkAccessDelegate> networkDelegate;
}
#property(nonatomic, assign) id networkDelegate;
-(void) initWithDelegate:(id) delegate; //
#end
NetworkAccessClass.m
#implementation
#synthesize networkDelegate
-(void) initWithParams:(id) delegate
{
networkDelegate = delegate;
// Assign GET/POST vals, create request etc
[request startAsynchronous];
}
-(void) requestSucceded:(ASIHTTPRequest *) request
{
if([networkDelegate respondsToSelector:#selector(requestSucceded:)]) {
// Send the data to the controller object for it to use
...
}
}
-(void) requestFailed:(ASIHTTPRequest *) request
{
// Same as above. Send to request failed.
}
#end
And finally in my FirstViewController.h
#import "NetworkAccessClass.h"
#interface FirstViewController<NetworkAccessDelegate>
{
}
-(void) requestSucceded:(NSData *) data;
-(void) requestFailed:(int) responseCode;
#end
And the same in SecondViewController.h and so on.
Although this does decouple my Controllers from my Network class, I can't help feel it's wrong because the controllers in this case are acting as delegates or helper methods to the Network Class and not the other way round. Am I missing something basic? Or is this how it is?
Thanks,
Teja.
Delegates aren't "helper methods". Think of them as objects that get notified when something happens. (Although don't confuse them with "Notifications"--that's a different thing entirely.) In this case, your network class does it's stuff and then calls its delegate method on the View Controller that instantiated and fired, it to report the contents of that response to the view controller. The controller will then, presumably, update the view with the data that the network connector got. Classic delegate pattern, right there.

objective-c delegate

i working with geocoding at the moment. The geocoding service allways works with delegates.
So let's say, I've got a
AskingClass and AnsweringClass(geocoding)
The AskingClass calls a function in the AnsweringClass to return the adress of the current location.
AnsweringClass should handle and capsulate the geocoding stuff. My Problem is, with all these delegates, I do not manage to come back to the orginal function, which the asking class has called. So I cannot give easily the adress back:
AskingClass.Adress= [AnsweringClass giveAdress];
I managed it, doing it with delegates, so the result comes back in a delegate function (somewhere) in the askingClass. But I'm not happy with that. It's seems oversized and complex.
with best regards
Klaus-Dieter
It is unclear why you are using a delegate pattern at all. Why not just use straight up classes?
Something like this (assuming that you are using a PCH file for your header files or otherwise importing 'em as needed):
AnsweringClass.h
#interface AnsweringClass:NSObject
- (MyAnswer *)answerThisDude;
#end
AskingClass.h
#class AnsweringClass; // just in case you including AskingClass.h before AnsweringClass.h
#interface AskingClass : NSObject
// {
// declare the ivar if you need support for 32 bit "classic" ABI
// AnsweringClass *theThingThatAnswers;
// }
#property(retain) AnsweringClass *theThingThatAnswers;
#end
Then you can do this:
AskingClass.m
#implementation AskingClass
#synthesize theThingThatAnswers;
- (void) setUpMyStuff // probably invoked by your designated initializer or app launch handler
{
self.theThingThatAnswers = [AnsweringClass new];
MyAnswer *theFirstAnswer = [self.theThingThatAnswers answerThisDude];
}
// don't forget a -dealloc if you aren't running GC'd
#end
No delegation necessary.