How do you get the NSURLConnection delegate methods to trigger? - iphone

I can't seem to get the delegate methods to call, when I load the view associated with this class.. none of them fire. I'm sure it's something that I've overlooked but I can't for the life of me figure out why.
DownloadUpdates.h
#import <UIKit/UIKit.h>
#interface DownloadUpdates : UIViewController
#property (strong, nonatomic) NSMutableData *responseData;
#property (strong, nonatomic) NSURLConnection *connection;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
#end
DownloadUpdates.m
The URL has been removed for privacy purposes, but it's just making a call to an API which will be returning JSON data. This URL functions as expected so it's an issue with the code.
#import "DownloadUpdates.h"
#interface DownloadUpdates ()
#end
#implementation DownloadUpdates
- (void)connection:(NSURLConnection *)_connection didReceiveResponse:(NSURLResponse *)response
{
_responseData = [[NSMutableData alloc] init];
NSLog(#"Response received");
}
- (void)connection:(NSURLConnection *)_connection didReceiveData:(NSData *)data
{
[_responseData appendData:data];
NSLog(#"Data received");
}
- (void)connection:(NSURLConnection *)_connection didFailWithError:(NSError *)error
{
NSLog(#"Unable to fetch data");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)_connection
{
NSLog(#"Succeeded! Received %d bytes of data",[_responseData
length]);
// NSString *txt = [[NSString alloc] initWithData:_responseData encoding: NSASCIIStringEncoding];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *myURL = [NSURL URLWithString:#"URL HERE"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I'd appreciate any help / advice you can offer.

Use the properties to apply the strong modifier:
self.responsedata = [[NSMutableData alloc] init];
(.....)
self.connection = [[NSURLConnection alloc] initWithRequest: ....etc...

I'd suggest putting a NSLog or breakpoint in viewDidLoad to make sure this is getting called at all. For example, this might happen if you neglected to specify DownloadUpdates as the class for your storyboard scene.

Related

I can't receive XML file from Weather Underground service

I'm trying to write a weather app that use wunderground api...
I've got an apiKey and I used it in the code below, but I can't see any result in debug area...
Xcode show me a warning in a line "EXPRESSION RESULT UNUSED"...Is this the problem?
Can anybody help me please?
#import "WeatherForecast.h"
#import "MainViewController.h"
#implementation WeatherForecast
- (void) queryServiceWithState:(NSString *)state
andCity:(NSString *)city
withParent:(UIViewController *)controller {
viewController = (MainViewController *)controller;
responseData = [NSMutableData data];
apiKey = #"c5f79118382c6e91";
NSString *url =
[NSString stringWithFormat:
#"http://api.wunderground.com/api/%#/conditions/q/%#//%#.xml",
apiKey, state, city];
theURL = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:theURL];
[[NSURLConnection alloc] initWithRequest:request delegate:self];//EXPRESSION RESULT UNUSED
}
#pragma mark NSURLConnection Delegate Methods
- (NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)response{
#autoreleasepool {
theURL = [request URL];
}
return request;
}
- (void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
-(void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Error = %#",error);
}
- (void)connectionDidFinishiLoading: (NSURLConnection *)connection {
NSString *content =
[[NSString alloc]initWithBytes:[responseData bytes]
length:[responseData length]
encoding:NSUTF8StringEncoding];
NSLog ( #"Data = %#",content);
//...Insert code to parse the content here...
[viewController updateView];
}
#end
I've got another 2 .m files for my app, maybe the error is in one of this
#import "MainViewController.h"
#import "WeatherForecast.h"
#interface MainViewController ()
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self refreshView:self];
}
- (IBAction)refreshView:(id)sender {
[loadingActivityIndicator startAnimating];
[self.forecast queryServiceWithState:#"UK" andCity:#"London" withParent:self];
}
- (void)updateView {
//...
[loadingActivityIndicator stopAnimating];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc]
initWithNibName:#"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES completion:nil];
}
#end
And
#import "AppDelegate.h"
#import "WeatherForecast.h"
#import "MainViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.mainViewController = [[MainViewController alloc]
initWithNibName:#"MainViewController" bundle:nil];
WeatherForecast *forecast = [[WeatherForecast alloc] init];
self.mainViewController.forecast = forecast;
self.window.rootViewController = self.mainViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
#end
If I try to turn off internet connection I can see in the debug area the "Error message", but if I turn on internet connection, so I only see the Activity Indicator spinning forever...
Thank you for your response....I feel lost...
Where you get EXPRESSION RESULT UNUSED is the connection object. You should usually be storing that into a property so you ensure that it isn't destroyed while you're still using it.

Appending data from downloaded from the web in NSMutableData

I'm trying to append data from a CSV file that I'm getting form the internet. Something is going wrong and I can't figure out what. My log is not returning anything for "Field" or "Value". I'm holding the data as NSMutableData and trying to append it. Am I overwriting it in any way? Something in the data storage/retrieval process must be going wrong... Could you pls take a look at this code and tell me if I'm doing something wrong:
#import "ViewController.h"
#import "CHCSVParser.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize parser = _parser;
bool isStatus;
#synthesize apendData;
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"connectionDidFinishLoading");
NSString *myString;
myString = [[NSString alloc] initWithData: apendData encoding:NSUTF8StringEncoding];
_parser = [[CHCSVParser alloc] initWithContentsOfCSVFile:[NSHomeDirectory() stringByAppendingPathComponent:myString]];
_parser.delegate = self;
[_parser parse];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"data: %#", data);
if (apendData)
[apendData appendData:data];
else
apendData = [[NSMutableData alloc] initWithData:data];
}
- (void)loadDatafromURL
{
NSURL *url = [NSURL URLWithString:#"http://www.google.com/trends/trendsReport?hl=en-US&cat=0-13&date=today%207-d&cmpt=q&content=1&export=1"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"%#", [error description]);
}
- (void)parser:(CHCSVParser *)parser didBeginLine:(NSUInteger)recordNumber
{
if (recordNumber == 41) {
isStatus = YES;
NSLog(#"ParsingStart..."); // Not getting this
}
}
- (void)parser:(CHCSVParser *)parser didEndLine:(NSUInteger)recordNumber
{
if (recordNumber == 50) {
NSLog(#"ParsingEnd..."); // Not getting this
[parser cancelParsing];
}
}
- (void)parser:(CHCSVParser *)parser didReadField:(NSString *)field atIndex:(NSInteger)fieldIndex
{
if ((isStatus = YES)) {
NSLog(#"YES is working");
if (fieldIndex == 0) {
NSLog(#"Field = %#", field); // Just getting "Field = "
}
if (fieldIndex == 1){
NSLog(#"Value = %#", field); // Not getting this
}
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadDatafromURL];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end

in app purchase response never comes

In my iPhone app, i've set up an in app purchase. I start the request like this:
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: #"com.nicknoble.tiprounder.upgrade"]];
request.delegate = self;
[request start];
And I use this method to get the response:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"response recieved");
}
And this one to catch an error:
-(void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
NSLog(#"%#",error.description);
}
But neither ever get called. My project has no warnings or errors, and I am running this on my device (iPhone). Any suggestions?
EDIT:
So it works on my window's root view controller, but not on modal view controllers i present. Here is the code from my main view controller:
TestViewController *testView = [[TestViewController alloc] initWithNibName:#"TestViewController" bundle:nil];
[self presentModalViewController:testView animated:YES];
Here is the .h file for TestViewController:
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>
#interface TestViewController : UIViewController <SKProductsRequestDelegate>
#end
Here is the code for my .m file:
#import "TestViewController.h"
#implementation TestViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: #"com.nicknoble.tiprounder.upgrade"]];
request.delegate = self;
[request start];
}
-(void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
NSLog(#"%#",error.description);
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"response recieved");
}
#end
Im desperate. Any help would be great! Thanks!
The SKProductsRequest instance need to be retained for the duration of the request. If it's not, it will die silently (without informing its delegate) because nothing else is retaining it.
Right now, ARC will get rid of your SKProductsRequest as soon as the code exits the scope where you allocate it.
A solution would be to keep your SKProductsRequest in an ivar and set it to nil when the request completes/fails. This is also handy to prevent starting a request while there's already one in progress:
// Define _productsRequest as an ivar of type SKProductsRequest in your class
- (void)someMethodThatInitiatesTheProductsRequest
{
if( _productsRequest != nil )
return; // There's already a request in progress. Don't start another one.
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: #"com.nicknoble.tiprounder.upgrade"]];
request.delegate = self;
[request start];
_productsRequest = request; // <<<--- This will retain the request object
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"response recieved");
_productsRequest = nil; // <<<--- This will release the request object
}
-(void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
NSLog(#"%#",error.description);
_productsRequest = nil; // <<<--- This will release the request object
}
check your product identifier first.
also check if the class in which these methods are implemented is not released somehow. (might be autoreleased and got released automatically while you are waiting for response)

I am Getting EXC_BAD_ACCESS while NSURLREQUEST

I am getting EXC_BAD_ACCESS while NSURLREQUEST.
I am giving pdf url from server to to webview through AppDelegate_iPhone's currentBookPressed.
please can anyone tell what is the problem ...
Code:-
#class AppDelegate_iPhone;
#interface PdfShowViewController : UIViewController<UIWebViewDelegate> {
UIWebView *pdfWebview;
AppDelegate_iPhone *appDelegate;
NSMutableData *receivedData;
UIActivityIndicatorView *myIndicator;
IBOutlet UIProgressView *progress;
NSURLRequest* DownloadRequest;
NSURLConnection* DownloadConnection;
long long bytesReceived;
long long expectedBytes;
}
#property (nonatomic,retain) UIWebView *pdfWebview;
#property (nonatomic,retain) UIActivityIndicatorView *myIndicator;
#property (nonatomic,retain) IBOutlet UIProgressView *progress;
#property (nonatomic,retain) NSMutableData *receivedData;
#property (nonatomic, readonly, retain) NSURLRequest* DownloadRequest;
#property (nonatomic, readonly, retain) NSURLConnection* DownloadConnection;
-(IBAction)onTapBack;
#end
#import "PdfShowViewController.h"
#import "AppDelegate_iPhone.h"
#implementation PdfShowViewController
#synthesize pdfWebview,myIndicator,progress,receivedData,DownloadRequest,DownloadConnection;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
unsigned char byteBuffer[[receivedData length]];
[receivedData getBytes:byteBuffer];
NSLog(#"Data === %ld",receivedData);
NSInteger receivedLen = [data length];
bytesReceived = (bytesReceived + receivedLen);
NSLog(#"received Bytes == %f",bytesReceived);
if(expectedBytes != NSURLResponseUnknownLength)
{
NSLog(#"Expected Bytes in if == %f",expectedBytes);
NSLog(#"received Bytes in if == %f",bytesReceived);
float value = ((float) (bytesReceived *100/expectedBytes))/100;
NSLog(#"Value == %f",value);
progress.progress=value;
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//[connection release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
expectedBytes = [response expectedContentLength];
NSLog(#"%f",expectedBytes);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[myIndicator stopAnimating];
[myIndicator removeFromSuperview];
pdfWebview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 40, 320, 420)];
[pdfWebview setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[pdfWebview setScalesPageToFit:YES];
[pdfWebview setAutoresizesSubviews:YES];
[pdfWebview loadRequest:DownloadRequest];
[self.view addSubview:pdfWebview];
//[connection release];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
myIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
myIndicator.center = self.view.center;
myIndicator.hidesWhenStopped = NO;
[self.view addSubview:myIndicator];
[myIndicator startAnimating];
//receivedData = [[NSMutableData alloc] initWithLength:0];
NSLog(#"%#",appDelegate.currentBookPressed);
NSString * urlString = [appDelegate.currentBookPressed stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSLog(#"%#",urlString);
NSURL *targetURL = [NSURL URLWithString:urlString];
NSLog(#"%#",targetURL);
// Here comes Acception
DownloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:targetURL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
DownloadConnection = [[NSURLConnection alloc] initWithRequest:DownloadRequest delegate:self];
if (DownloadConnection) {
receivedData = [[[NSMutableData data]initWithLength:0]retain];
}
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
-(IBAction)onTapBack
{
[self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[super dealloc];
[pdfWebview release];
[receivedData release];
}
#end
You should replace line
DownloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:targetURL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
with line
DownloadRequest = [NSURLRequest requestWithURL:targetURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
It is because method requestWithURL:cachePolicy:timeoutInterval: in first parameter is waiting for object of NSURL class. In targerURL you have exactly that one.
Moreover in method [NSURL URLWithString:targetURL] (if you will need it) you should pass NSString as a first parameter, but you are passing NSURL.
Your problem in this line
DownloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:targetURL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
The problem in your case arises because parameter for + (id)URLWithString:(NSString *)URLString is NSString and you are passing NSURL and method trying to get the length of the supposed string by calling -length, which exists for NSString but not for NSURL.

NSURLConnection doesn't call didRecieveData method

I want my application to download some data from the internet, in iPhone SDK documentation
i found NSURLConnection class, which is used for downloading, Am i right?
I wrote the same code as it is in the documentation and ran it. Connection was created successfully, but no data were downloaded. connectionDidFinishLoading is fired after sec or two but with no data in result. Problem is, that didRecieveData method is never fired. I dont know why, i searched the internet, but every result was the same code as it is in the documentation. Could you give an advice please? Thanks for every reply
My downloader class source code is below.
Downloader.h
#interface Downloader : NSObject {
NSURLConnection *conn;
//Array to hold recieved data
NSMutableData *recievedData;
}
#property (nonatomic, retain) NSURLConnection *conn;
#property (nonatomic, retain) NSMutableData *recievedData;
- (void)downloadContentsOfUrl:(NSURL *)url;
#end
Downloader.m
#import "Downloader.h"
#implementation Downloader
#synthesize recievedData, conn;
- (void)connection:(NSURLConnection *)connection didRecieveResponse:(NSURLResponse *)response
{
NSLog(#"did recieve response");
[recievedData release];
recievedData = nil;
}
- (void)connection:(NSURLConnection *)connection didRecieveData:(NSData *)data
{
NSLog(#"did recieve data");
//Append the new data to the recieved data
[recievedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//Release the connection and the data object
[connection release];
[recievedData release];
NSLog(#"Connection failed! Error - %# %#", [error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//ToDo with data
//[recievedData writeToFile:#"data" atomically:YES];
NSLog(#"downloaded");
NSLog(#"%u", [recievedData length]);
//Release the connection and the data object
[connection release];
[recievedData release];
}
- (void)downloadContentsOfUrl:(NSURL *)url
{
//Create the connection
//Create the request
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
//Create the connection with the request and start loading the data
conn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self
startImmediately:YES];
if(conn)
{
//Create the NSMutableData that will hold the recieve data
recievedData = [[NSMutableData data] retain];
NSLog(#"Connection success!");
}
else
{
NSLog(#"Can't download this file!");
}
}
- (void)dealloc
{
[conn release];
[recievedData release];
[super dealloc];
}
You've misspelt "receive":
// Your signature
- (void)connection:(NSURLConnection *)connection didRecieveData:(NSData *)data;
// Correct signature
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
You have a typo in the name of your didReceiveData method (i before e, except after c :-)
Thus it will look like your class doesn't implement that (optional) selector and it will be silently ignored.