use of undeclared identifier - objective-c

I am new to Objective-C coding ,please bear with me to ask if this is simple question
My Header file:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*) response;
#end
My Implementation file:
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSMutableData *receivedData =[NSMutableData dataWithCapacity: 0];
// Create the request
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.apple.com/"] cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData dataWithCapacity: 0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (!theConnection) {
// Release the receivedData object.
receivedData = nil;
// Inform the user that the connection failed.
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSMutableData *receivedData =[NSMutableData dataWithCapacity:0];
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse object.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere.
[receivedData setLength:0];
}
#end
when i run the code at implementation appDelegate it gives warning
Method definition for connection:didRecieveResponse :not found
and where
-(void)connection line it gives "use of undelcared identifier connection did u mean Collection".

You do not need to declare the method
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*) response;
in your header file if you are using the NSURLConnectionDataDelegate Protocol in your code. Just add the protocol in the implementation and use the methods from that protocol.

Related

Objective-C issue with connectionDidFinishLoading and Delegate

Am trying to use an API class to fetch data from a URL and then have that data returned to a method inside the ViewController. I have the ViewController call the API method.
Have tried several places on SO already and come up with the following, but it is not working and as an Objective-C noobie have tried reading documentation and such but still not understanding what could be going wrong.
I have a viewcontroller calling an method 'fetch' inside a class 'api'.
I have the connection delegates inside api class and it works ok (correct data is printed inside connectionDidFinishLoading method).
I need a delegate to return the data to a method inside the viewcontroller class.
So far I have
ViewController.h
#import "Api.h"
#interface ViewController : UIViewController <apiDelegate>{
}
- (void)apiSucceeded:(NSString *)jsonString;
- (void)apiFailed:(NSString *)failedMessage;
#end
ViewController.m
#import "ViewController.h"
#import "Api.h"
- (void)apiSucceeded:(NSString *)jsonString {
NSLog(#"WORKED");
}
- (void)apiFailed:(NSString *)failedMessage {
NSLog(#"FAILED");
}
- (void)viewDidLoad {
[super viewDidLoad];
Api* myapi = [[Api alloc]init];
[myapi fetch];
}
#end
Api.h
#protocol apiDelegate
#required
- (void)apiSucceeded:(NSString *)jsonString;
- (void)apiFailed:(NSString *)failedMessage;
#end
#interface Api : NSObject {
id _delegate;
}
#property (nonatomic, assign) id _delegate;
-(void)fetch;
#end
Api.m
#import "Api.h"
#import "ViewController.h"
#synthesize _delegate;
- (void)fetch{
//connection setup....
[NSURLConnection connectionWithRequest:[request autorelease] delegate:self];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.receivedData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// NSLog(#"append data");
[self.receivedData appendData:data];
// NSLog(#"Bytes: %d", [receivedData length]);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//TODO error handling for connection
if ([_delegate respondsToSelector:#selector(apiFailed:)]) {
[_delegate apiFailed:[error localizedDescription]];
}
NSLog(#"Cannot Connect");
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [self.receivedData length]);
NSString *jsonString = [[NSString alloc] initWithBytes: [receivedData mutableBytes] length:[receivedData length] encoding:NSUTF8StringEncoding];
if ([_delegate respondsToSelector:#selector(apiSucceeded:)]) {
[_delegate apiSucceeded:jsonString];
}
}
#end
There is no error but it just does not run 'apiSucceeded' method.
Please dont misunderstand this as a question regarding 'connectionDidFinishLoading'. That bit works well, its the handing of the data BACK to a ViewController that is causing issues.
Can anybody see what I have done wrong please?
I seems that you forgot to set
myapi.delegate = self;
after
Api* myapi = [[Api alloc]init];

Pass NSArrays from ViewController to NSObject class

I have a single view application where the ViewController contains a UIView of custom class CPTGraphHostingView so that it holds a CorePlot graph. The content of that UIView is managed by an NSObject sub-class called SimpleScatterPlot. This SimpleScatterPlot object holds all the parameters needed to configure the graph (axis ranges, labels, number of points, etc.)
ViewController.h
#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"
#import "SimpleScatterPlot.h"
#interface ViewController : UIViewController
{
IBOutlet CPTGraphHostingView *_graphHostingView;
SimpleScatterPlot *_scatterPlot;
NSMutableData *dataConexion;
}
#property (nonatomic,strong) NSArray *valor;
#property (nonatomic,strong) NSArray *strAnoMes;
#property (nonatomic,strong) NSArray *indicador;
#property (nonatomic, retain) SimpleScatterPlot *scatterPlot;
#end
In ViewController.m I have some methods to initialise a few arrays from some JSON data:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize indicador,valor,strAnoMes;
- (void)viewDidLoad
{
[super viewDidLoad];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *urlString = #"http://xxxx/ios/datosgrafica.php";
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
(void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
dataConexion = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[dataConexion appendData:theData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
indicador = [NSJSONSerialization JSONObjectWithData:dataConexion options:nil error:nil];
// ARRAYS OF INTEREST
strAnoMes = [indicador valueForKey:#"StrAnoMes"];
valor = [indicador valueForKey:#"Valor"];
self.scatterPlot = [[SimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:pointArray];
[self.scatterPlot initialisePlot];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The download could not complete - please make sure you're connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
In the SimpleScatterPlot.m I would like to use the array "valor" to configure axis ranges, and I would like to use the array "strAnoMes" to draw custom labels in the xAxis.
What do I have to do so that I can pass those arrays defined in ViewController to SimpleScatterPlot?
I have tried to #import "ViewController.h" but it gives me errors. Any other ideas? What is the best way to approach this situation?
You can take two properties in SimpleScatterPlot.
SimpleScatterPlot.h
#property (nonatomic, retain) NSArray * strAnoMes;
#property (nonatomic, retain) NSArray * valor;
SimpleScatterPlot.m
#synthesize strAnoMes;
#synthesize valor;
In ViewController.m, After creating scatterPlot in connectionDidFinishLoading:, assign the values to above properties as below.
self.scatterPlot.strAnoMes = strAnoMes;
self.scatterPlot.valor = valor;
One way to do this is to create a simple data object and pass it directly into your SimpleScatterPlot object:
Data Object:
#interface SimpleScatterPlotData : NSObject
#property (...) NSArray *valor;
#property (...) NSArray *strAnoMes;
#end
#implementaton SimpleScatterPlotData
#synthesize valar;
#synthesize strAnoMes;
-(void)dealloc
{
...
...
[super dealloc];
}
#end
Implement a load method in your SimpleScatterPlot class:
#interface SimpleScatterPlot
-(void)loadData:(SimpleScatterPlotData *)data;
#end
#implementation SimpleScatterPlot
-(void)loadData:(SimpleScatterPlotData *)data
{
NSArray *valor = data.valor;
NSArray *strAnoMes = data.strAnoMes;
/*
Do something
*/
}
#end
Then in your ViewController class:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
indicador = [NSJSONSerialization JSONObjectWithData:dataConexion options:nil error:nil];
// ARRAYS OF INTEREST
strAnoMes = [indicador valueForKey:#"StrAnoMes"];
valor = [indicador valueForKey:#"Valor"];
SimpleScatterPlotData *data = [[[SimpleScatterPlotData alloc] init] autorelease];
data.valor = valor;'
data.strAnoMes = strAnoMes;
self.scatterPlot = [[SimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:pointArray];
[self.scatterPlot loadData:data];
}
You could also change your current initializer or add a new initializer to your SimpleScatterPlot class so that you pass those arrays in when you alloc the object. So your the call to your initializer would look something like:
self.scatterPlot = [[SimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:pointArray andValor:valor andstrAnoMes:strAnoMes];
Then in your initializer you can set the object properties to those passed in values.

NSURLConnection returns old data although NSURLRequestReloadIgnoringLocalAndRemoteCacheData

I’ve got a serious problem. In my app I m downloading a XML-File using NSURLConnection. So far so good. But from time to time, the NSURLConnection returns an old version of the requested file although I set The cachePolicy to NSURLRequestReloadIgnoringLocalAndRemoteCacheData.
The really disgusting part of the bug is, that the connection always return the old version of the file until I active and then deactivate the airplane mode or I rebooted the device.
An other interesting fact is: When I activate Wifi and call the app to reload the file the correct and actual version of the file is returned. But after turning off Wifi the old version is retuned again.
I m really becoming desperate with this problem and hope anybody can help me?
Here is the code from my class, downloading the file:
#import "HTTPReciever.h"
#import "Constants.h"
#interface HTTPReciever ()
#property (strong, nonatomic) NSMutableData *receivedData;
#property (strong, nonatomic) NSString *directoryPath;
#property (strong, nonatomic) NSString *filename;
#property (assign, nonatomic) BOOL storeData;
#end
#implementation HTTPReciever
#synthesize receivedData = _receivedData;
#synthesize delegate = _delegate;
#synthesize directoryPath = _directoryPath;
#synthesize filename = _filename;
- (BOOL)recieveDataFromURL:(NSURL *)url
storeAtDirectoryPath:(NSString *)directoryPath
withName:(NSString *)name
{
[self setDirectoryPath:directoryPath];
[self setFilename:name];
[self setStoreData:YES];
return [self recieveDataFromURL:url];
}
- (BOOL)recieveDataFromURL:(NSURL *)url
{
NSURLRequest *theRequest = [[NSURLRequest alloc] initWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:cDefaultHTTPTimeOutInterval];
self.receivedData = nil;
self.receivedData = [[NSMutableData alloc] initWithLength:0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:theRequest
delegate:self
startImmediately:NO];
if ([NSURLConnection canHandleRequest:theRequest] && connection) {
[connection start];
return YES;
} else {
return NO;
}
}
#pragma mark - NSURLConnectionDelegate protocol
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data
{
[self.receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[self.receivedData setLength:0];
if ([response isKindOfClass:[NSHTTPURLResponse self]]) {
NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields];
NSString *modified = [headers objectForKey:#"Last-Modified"];
if (modified) {
// not yet used
}
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if (self.storeData) {
[[NSFileManager defaultManager] createDirectoryAtPath:self.directoryPath
withIntermediateDirectories:YES
attributes:nil
error:nil];
[self.receivedData writeToFile:[NSString stringWithFormat:#"%#%#", self.directoryPath, self.filename]
atomically:YES];
}
[self.delegate receiver:self
didFinishLoadingData:self.receivedData
lastVersion:YES];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
[self.delegate receiverFailedLoadingData:self];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
#end

Getting the NSURLConnection delegate callback into the right thread

I can't seem to get a Delegate callback to work when I thread my code. I am trying to call a remote server using NSURLConnection to get an access_token. The access_token is received in connection:didReceiveResponse: delegate. This is not a problem until I thread it. I thought I was passing the correct objects for my delegates, but it does not reach connection:didReceiveResponse:
Can anyone see why connection:didReceiveResponse: in LoginViewController does not get called when I thread the call? Thanks.
LoginViewController.m
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSString *access_token = [self getTokenFromResponse: response];
[self.delegate didGetAccessToken:access_token];
}
- (void)fetchAccessTokenNoUI
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: #"www.mysite.com"]];
[NSURLConnection connectionWithRequest:request delegate:self];
}
AccessToken.h
#interface AccessToken : NSObject
#property (atomic, strong) LoginViewController *loginViewController; // doing this to try to keep it persistent
- (void) fetchAccessTokenWithDelegate: (id <LoginDelegate>)delegate;
#end
AccessToken.m
- (void) fetchAccessTokenWithDelegate: (id < LoginDelegate >)delegate
{
dispatch_queue_t downloadQueue = dispatch_queue_create("Fetch access_token queue", NULL);
dispatch_async(downloadQueue, ^ {
// this works fine if I don't do it in a queue
self.loginViewController = [[LoginViewController alloc] init];
self.loginViewController.delegate = delegate;
[self.loginViewController fetchAccessTokenNoUI];
});
dispatch_release(downloadQueue);
}
CallingClass.m
- (void)didGetAccessToken:(NSString *)access_token
{
if (!access_token)
{
LoginViewController *userProfileViewController = [[LoginViewController alloc] init];
userProfileViewController.delegate = self;
[self.navigationController pushViewController:userProfileViewController animated:YES];
}
}
- (IBAction)favourite:(id)sender
{
AccessToken *accessToken = [[AccessToken alloc] init];
[accessToken fetchAccessTokenWithDelegate:self];
}
So after some more research, I found the solution.
I don't actually need AccessToken.h/m. I thought that the NSURLConnection call would block my UI thread. But NSURLConnection connectionWithRequest:delegate: is automatically run in a separate thread.
So all I have to do is delete AccessToken.h and AccessToken.m. Then, in CallingClass.m, I change favourte: to
- (IBAction)favourite:(id)sender
{
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[loginViewController fetchAccessTokenWithDelegate:self];
}
That's it! Don't need to dispatch_queue_t at all.
Have you put stubs to implement the required protocol methods,
-(void)connectionDidFinishLoading:(NSURLConnection *)connection;
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
Because I had a similar problem which went away after implementing them.

NSUrlConnection in NSThread - No delegate is executed!

I am using an NSURLConnection in an NSThread but none of the NSURLConnection's delegate methods are executed! I have a main method in my NSTread subclass and a while loop that keeps the thread active. Any help?
Sorry for all of this code but I think its the best way to describe my problem. So this is an object that does the async connection calling createConnectionWithPath:userObjectReference
#interface WSDAsyncURLConnection : NSObject
{
NSMutableData *receivedData;
NSDate *connectionTime;
NSURLConnection *connection;
id _theUserObject;
}
#property (nonatomic, retain) NSMutableData *receivedData;
#property (nonatomic, retain) NSDate *connectionTime;
#property (nonatomic, assign) NSURLConnection *connection;
- (void)createConnectionWithPath:(NSString *)thePath userObjectReference:(id)userObject;
#end
#import "WSDAsyncURLConnection.h"
#implementation WSDAsyncURLConnection
#synthesize connectionTime, receivedData, connection;
- (void) terminate
{
if (self.connection) {
[self.connection release];
self.connection = nil;
}
}
- (void) createConnectionWithPath:(NSString *)thePath userObjectReference:(id)userObject;
{
_theUserObject = userObject;
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:thePath]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
self.connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
if (self.connection)
{
/* record the start time of the connection */
self.connectionTime = [NSDate date];
/* create an object to hold the received data */
self.receivedData = [NSMutableData data];
}
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.receivedData setLength:0];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
/* appends the new data to the received data */
[self.receivedData appendData:data];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[self terminate];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
// displays the elapsed time in milliseconds
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSinceDate:self.connectionTime];
// displayes the length of data received
NSUInteger length = [self.receivedData length];
NSString* aStr = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
[self terminate];
[[NSNotificationCenter defaultCenter] postNotificationName:WSDAsynchURLConnectionDidFinished
object:_theUserObject
userInfo:[NSDictionary dictionaryWithObject:aStr forKey:#"urlResponseString"]];
NSLog(#"ti=%f, l=%d, response=%#", elapsedTime, length, aStr);
}
#end
This code is mostly from an apple's example project and it works fine outside an NSThread.
But when I use it in the following thread subclass no delegate method is executed !!
#implementation IncomingThread
- (void) main {
NSAutoreleasePool *poool = [[NSAutoreleasePool alloc] init];
// I start the URLConnection here ... But no delegate is executed !
[urlConn createConnectionWithPath:#"http://localhost:8888" userObjectReference:nil];
while (![self isCancelled]) {
[NSThread sleepForTimeInterval:3.];
}
[poool release];
}
- (id) init
{
self = [super init];
if (self != nil) {
urlConn = [[WSDAsyncURLConnection alloc] init];
}
return self;
}
- (void) dealloc {
NSLog(#"deallocating (%#)...", [self className]);
[urlConn release];
[super dealloc];
}
First of all: you don't need to use NSURLConnection in the separate thread. Since it is asynchronous it doesn't block the main thread.
Second: there is not processing of your connection because you always stop the execution of the thread's runloop with this peace of code:
while (![self isCancelled]) {
[NSThread sleepForTimeInterval:3.];
}
From the docs for the sleepForTimeInterval:
No run loop processing occurs while the thread is blocked.
You’re doing this the hard way. NSURLConnection does not play very nice with threads, since it needs a run loop to work. Your thread does not have a run loop and therefore the code does not work. Why not run the connection on the main thread? Or you can wrap the connection in an NSOperation, sample code here. And nowadays you also have the option to use a synchronous connection and dispatch it to a global GCD queue.
Did you remember to assign the delegate?
Something like:
self.connection.delegate = self;
Just because your class WSDAsyncURLConnection implements the delegate methods, doesn't mean they are being called.
Late but it may save others life :)
Solution link is : NSURLConnection delege methods does not work