NSNotificationCenter and ASIHTTPRequest - iphone

I hope to get the http header info(file size) in asynchronous mode.
So I initialize as codes:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(processReadResponseHeaders:) name:#"readResponseHeaders"
object:nil];
my codes to read the http header
-(void)processReadResponseHeaders: (ASIHTTPRequest *)request ;//(id)sender;
{
unsigned long long contentLength = [request contentLength]; //error occurs here
}
It has to change the source code of ASIHTTPRequest.m
I did add my codes in function readResponseHeaders to notify the event is triggered )
- (void)readResponseHeaders
{
//.........................
[[NSNotificationCenter defaultCenter] postNotificationName:#"readResponseHeaders" object:self];//
}
the log file reports:
2010-05-15 13:47:38.034 myapp[2187:6a63] *** -[NSConcreteNotification contentLength]: unrecognized selector sent to instance 0x46e5bb0
Welcome any comment
Thanks
interdev

NSNotificationCenter's observers' selector must have one of the signatures:
-(void)observe;
-(void)observeWithNotification:(NSNotification*)notification;
It cannot be an ASIHTTPRequest (even if you put ASIHTTPRequest* in the argument, it is still an NSNotification.)
There are 3 properties of NSNotification: name, object and userInfo. You could obtain the ASIHTTPRequest with object, if self is an ASIHTTPRequest when you post that notification:
-(void)processReadResponseHeaders:(NSNotification*)notification {
ASIHTTPRequest* request = [notification object];
unsigned long long contentLength = [request contentLength];
...
}

Related

postNotification trigger the function correctly , but userinfo(NSDictionary) has nothing

I used the codes below to notify the menu selection index
NSDictionary *userInfo= [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"123"]
forKey:#"Index"];
[[NSNotificationCenter defaultCenter] postNotificationName: #"notifyToMenuSelectionNotification"
object: userInfo];
-(void)menuSelectionNotification:(NSNotification *)notification
{
NSLog(#"%#", notification.userInfo);
}
menuSelectionNotification is triggered correctly,
but NSLog output notification.userInfo is still {null}
Welcome any comment1
you are passing object in wrong way. Please try this -
NSDictionary *userInfo= [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"123"]
forKey:#"Index"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"notifyToMenuSelectionNotification"
object:nil
userInfo:userInfo];
You have to set your dictionary as the userInfo parameter, not as the object. You may want to try
[[NSNotificationCenter defaultCenter] postNotificationName:#"notifyToMenuSelectionNotification" object:nil userInfo:userInfo];
You should post the dictionary in userInfo parameter , like
[[NSNotificationCenter defaultCenter] postNotificationName:#"notifyToMenuSelectionNotification" object:nil userInfo:userInfo];
For more detail, pl. see the NSNotificationCenter documentation
please try this
[[NSNotificationCenter defaultCenter] postNotificationName:#"notifyToMenuSelectionNotification" object:userInfo userInfo:nil];
-(void)menuSelectionNotification:(NSNotification *)notification{
NSDictionary *userInfo = (NSDictionary*)notification.object;
}

iphone - connection recovered callback

I would like to know if there's an automatic way of knowing when the connection was recovered.
My app connects to a webservice, lets say the network is not available in that moment so the app won't get the info from the server, but I would like the app to automactily try to reconect to the server if it "feels" that the connection was recovered.
Is there such a callback?
In whatever class you handle your NSURLConnection you need to add some connection check. So below I have posted an example
Create a Reachability instance
Add an observer to the Reachability did change notification
When the connection will change the - (void)networkReachabilityDidChange:(NSNotification *)notification will be fired.
You obviously check the networkStatus before firing off a connection in the first place.
-(id)init
{
self = [super init];
if(self)
{
Reachability* newInternetReachability = [Reachability reachabilityForInternetConnection];
[newInternetReachability startNotifier];
self.networkReachability = newInternetReachability;
networkStatus = [self.networkReachability currentReachabilityStatus];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(networkReachabilityDidChange:) name:kReachabilityChangedNotification object:nil];
}
return self;
}
- (void) startHTTPRequest
{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:YOUR_URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:YOUR_REQUEST_TIMEOUT];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest: delegate:self];
}
- (void)networkReachabilityDidChange:(NSNotification *)notification
{
Reachability *currReach = [notification object];
NSParameterAssert([currReach isKindOfClass: [Reachability class]]);
int currStatus = [currReach currentReachabilityStatus];
// Check that current reachability is not the same as the old one
if(currReach != self.networkReachability)
{
switch (currStatus) {
case ReachableViaWiFi:
// fire off connection
[self startHTTPRequest];
break;
case ReachableViaWWAN:
// Fire off connection (3G)
[self startHTTPRequest];
break;
case NotReachable:
// Don't do anything internet not reachable
break;
default:
break;
}
[self updateReachability];
}
This is only a simple example but you probably need to persist the request until the connection has become available so you can fire it off later. This could be done via NSOperationQueue or something similar.
There isn't such a thing from the standard library perspective. You will have to implement that yourself. You could use apple's Reachability code to listen for network changes. So once you receive a notification from the Reachability code saying that the internet is now connected, you could fire off an URL connection. If you need an example I could mock something up quickly for you.

returning UIImage from block

I have the following code:
- (UIImage *) getPublisherLogo
{
//check the cache if the logo already exists
NSString * imageUrl = [NSString stringWithFormat:#"%#/%#&image_type=icon", self.baseUrl, self.imageUrl_];
ASIHTTPRequest * imageRequest = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:imageUrl]];
[imageRequest setTimeOutSeconds:30.0];
[imageRequest setDownloadCache:[ASIDownloadCache sharedCache]];
[imageRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[imageRequest setCachePolicy:ASIAskServerIfModifiedWhenStaleCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy];
[imageRequest setCompletionBlock:^(void){
UIImage *img = [UIImage imageWithData:[imageRequest responseData] ];
if (img){
return img;
}
}];
[imageRequest setFailedBlock:^(void){
NSLog(#"Error in pulling image for publisher %#", [[imageRequest error] userInfo]);
}];
[imageRequest startAsynchronous];
}
}
The issue is that the return value/UIImage is returned at a block. How do I avoid this?
You're unable to return anything from the completion block because it's returned void.
You'll probably need to create a new method like setLogo:(UIImage *)image on the object that's expecting the image to be set, and call that method from within the completion block.
You can place your img pointer outside the block and declare it __BLOCK and use it as a closure. But you really need to be asking yourself what do you plan to do with img, bearing in mind the call is made asynchronously. I would imagine you should make another call in the block to another method and pass in the populated image as a parameter.
For getting an object from the ASIHttpRequest response, I use notifications.
For example, in the calling viewController
- (void)viewDidLoad {
// Subscribe notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onGetPhoto:) name:#"getPhotoNotification" object:nil];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Unsubscribe from notifications
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"getPhotoNotification" object:nil];
}
- (void)onGetPhoto:(NSNotification *)notification {
...
}
in your completion block
[[NSNotificationCenter defaultCenter] postNotificationName:#"getPhotoNotification" object:self userInfo:userInfo];
With your photo in userInfo.

connectionDidFinishLoading:connect is never called when debugging on device

I am debugging my IOS5 application on the device for the first time and it is behaving very strangely. My application makes asynchronous http calls. When these calls complete I am posting notifications to handle the returned values. This all works great on the simulator. However on the device, it appears that the connectionDidFinishLoading:connection NSURLConnection delegate method is never called.
What is even stranger is the application then runs the incorrectly notification handler.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
SBJsonParser *jsonParser = [[SBJsonParser alloc]init];
NSError *error = nil;
id jsonObject = [jsonParser objectWithString:responseString error:&error];
switch (currentRequestType) {
case USER_EXISTS:{
NSNumber *userExists =[jsonObject objectForKey:#"exists"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"userExistsNote" object:userExists];
}
break;
case REGISTER_USER:{
NSNumber *success =[jsonObject objectForKey:#"success"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"registerUserNote" object:success];
}
case AUTHENTICATE_USER:{
NSNumber *success =[jsonObject objectForKey:#"success"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"authenticateUserNote" object:success];
}
default:
break;
}
}
The above switch statement delegates which notification should be posted. This peice of code never seems to run when debugging on the device however the method listening for the "registerUserNote" notification runs.. though the "authenticateUserNote" should have posted.
Again.. this all works great in the simulator.
Any ideas?
Thanks!

How to pass userInfo in NSNotification?

I am trying to send some data using NSNotification but get stuck. Here is my code:
// Posting Notification
NSDictionary *orientationData;
if(iFromInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
orientationData = [NSDictionary dictionaryWithObject:#"Right"
forKey:#"Orientation"];
}
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:#"Abhinav"
object:nil
userInfo:orientationData];
// Adding observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged)
name:#"Abhinav"
object:nil];
Now how to fetch this userInfo dictionary in my selector orientationChanged?
You get an NSNotification object passed to your function. This includes the name, object and user info that you provided to the NSNotificationCenter.
- (void)orientationChanged:(NSNotification *)notification
{
NSDictionary *dict = [notification userInfo];
}
Your selector must have : to accept parameters.
e.g.
#selector(orientationChanged:)
then in the method declaration it can accept the NSNotification parameter.
You are posting the notification correctly.
Please modify the Notification Observer like following.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:)
name:#"Abhinav" object:nil];
- (void)orientationChanged:(NSNotification *)notification
{
NSDictionary *dict = [notification userInfo];
}
I hope, this solution will work for you..
In swift
To get userinfo object
let dict = notification.userInfo
print(dict)