I am developing an application through which user can share images.Using php file I am uploading file on the server and downloading using php file.when i download file it is take bit long time.How do i make it little bit fast.
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSString *data1 = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSArray *arrImg = [data1 componentsSeparatedByString:#"###"];
int i;
NSMutableArray *receivedUrlArr = [[NSMutableArray alloc]init];
NSString *str,*strNew,*path;
NSData *imageData;
ImagesClass *obj;
int count;
for ( i=0; i<[arrImg count]-1; i++) {
[receivedUrlArr addObject:[arrImg objectAtIndex:i]];
str = [NSString stringWithFormat:#"http:////receive_images/%#",[receivedUrlArr objectAtIndex:i]];
strNew = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
UIImage *myImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:strNew]]];
obj = [[ImagesClass alloc]init];
obj.imageId = i+1;
obj.imageName = [[arrImg objectAtIndex:i] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
obj.thumbImage = myImage;
[[DBModel database]inserttoReceivedList:obj receiverMobNo:mobileno];
path = [RECEIVEDIMAGE_DIR stringByAppendingPathComponent:[NSString stringWithFormat:#"%#",obj.imageName]];
imageData = UIImagePNGRepresentation(obj.thumbImage);
[imageData writeToFile:path atomically:YES];
}
}
Thanks in advance.
No matter how efficient your method for storing an image is, you will always be bottlenecked by the speed of the connection.
However, you seem to be going about this the wrong way. -connection:didReceiveData is for receiving data incrementally. It seems that you are assuming that once you receive the data, you have finished loading the image, then doing a complicated bit of processing to save the partially downloaded image. Instead, your delegate for NSURLConnection should implement -connectionDidFinishLoading. In this method, you will convert the concatenated data to an image and save it then.
Here is how I would set things up:
Let's assume you have a controller class that is displaying images/needs to download more images.
Now, create a class named something like "ImageDownloader" which implements NSURLConnection Delegate. When you initialize this class, you will provide it with an image name and a URL to the image that needs to be downloaded. Within ImageDownloader, you will need an NSMutableData property. Finally, you will need a method such as -startDownload to get things moving.
-startDownload should first make sure that your NSMutableData property is empty and initialized. Once that's done, you can start the NSURLConnection's download. Be sure to set the delegate to your instance of ImageDownloader. In -connection:didReceiveData, append the data that is received to your NSMutableData property. In -connectionDidFinishLoading, convert that NSMutableData property to an image and save it using the image's name that your controller provided. From there, let the controller instance know the image is saved through a delegate method call or a notification.
Hope this helps.
edit: IIRC, Apple provides some sample code called "ImageDownloader" which is pretty similar if this explanation is confusing.
I have developed a class called File Downloader which is depicted as below :
Step 1 : Create a "FileDownloader.h" and add this in it.
#import <Foundation/Foundation.h>
#protocol fileDownloaderDelegate <NSObject>
#optional
- (void)downloadProgres:(NSNumber*)percent forObject:(id)object;
#required
- (void)downloadingStarted;
- (void)downloadingFinishedFor:(NSURL *)url andData:(NSData *)data;
- (void)downloadingFailed:(NSURL *)url;
#end
#interface FileDownloader : NSObject
{
#private
NSMutableURLRequest *_request;
NSMutableData *downloadedData;
NSURL *fileUrl;
id <fileDownloaderDelegate> delegate;
double totalFileSize;
}
#property (nonatomic, strong) NSMutableURLRequest *_request;
#property (nonatomic, strong) NSMutableData *downloadedData;
#property (nonatomic, strong) NSURL *fileUrl;
#property (nonatomic, strong) id <fileDownloaderDelegate> delegate;
- (void)downloadFromURL:(NSString *)urlString;
#end
Step 2 : Create a "FileDownloader.m" and write following
#import "FileDownloader.h"
#implementation FileDownloader
#synthesize _request, downloadedData, fileUrl;
#synthesize delegate;
- (void)downloadFromURL:(NSString *)urlString
{
[self setFileUrl:[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
self._request = [NSMutableURLRequest requestWithURL:self.fileUrl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0f];
NSURLConnection *cn = [NSURLConnection connectionWithRequest:self._request delegate:self];
[cn start];
}
#pragma mark - NSURLConnection Delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if([delegate respondsToSelector:#selector(downloadingStarted)])
{
[delegate performSelector:#selector(downloadingStarted)];
}
totalFileSize = [response expectedContentLength];
downloadedData = [NSMutableData dataWithCapacity:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[downloadedData appendData:data];
if([delegate respondsToSelector:#selector(downloadProgres:forObject:)])
{
[delegate performSelector:#selector(downloadProgres:forObject:) withObject:[NSNumber numberWithFloat:([downloadedData length]/totalFileSize)] withObject:self];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if([delegate respondsToSelector:#selector(downloadingFailed:)])
{
[delegate performSelector:#selector(downloadingFailed:) withObject:self.fileUrl];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if([delegate respondsToSelector:#selector(downloadingFinishedFor:andData:)])
{
[delegate performSelector:#selector(downloadingFinishedFor:andData:) withObject:self.fileUrl withObject:self.downloadedData];
}
}
#end
Step 3 : Now Import "#import "FileDownloader.h"" in your viewcontroller and "fileDownloaderDelegate" Delegate in .h file
Step 4 : Create Object , Set Delegate and URL to Download file.
FileDownloader *objDownloader = [[FileDownloader alloc] init];
[objDownloader setDelegate:self];
[objDownloader downloadFromURL:#"yourURL"];
Step 5 : Dont forget to implement Delegate methods in your view controller to get notify about download progress. enjoy..
Related
I need basically just a table view that showed recent tweets from either a #username or a #hashtag in a tableviewcontroller. No requirements to post tweets or anything like that.
Currently I use MGTwitterEngine it is complicated and only fetches username related tweets not hastags.
I found this tutorial but most of the codes is not explained and there is no source code.
Also find this but it seems http://search.twitter.com/search?q=%23+ #hashtag returns nil data
Also saw this question edited code for ARC and used http://search.twitter.com/search.json?q=%23epicwinning+OR+%40charliesheen link to fetch data
#import <Foundation/Foundation.h>
#protocol latestTweetsDelegate
- (void)returnedArray:(NSArray*)tArray;
#end
#interface latestTweets : NSObject
{
NSMutableData *responseData;
NSMutableArray *resultsArray;
id<latestTweetsDelegate> delegate;
}
#property (nonatomic, strong) NSMutableArray *resultsArray;
#property (strong,nonatomic) id<latestTweetsDelegate> delegate;
- (id)initWithTwitterURL:(NSString *)twitterURL;
#end
#import "latestTweets.h"
#import "SBJson.h"
#implementation latestTweets
#synthesize resultsArray, delegate;
- (id)initWithTwitterURL:(NSString *)twitterURL
{
self = [super init];
if (self) {
responseData = [NSMutableData data];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:twitterURL]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Connection failed: %#", [error description]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSArray *newData = [responseString JSONValue];
[self.delegate returnedArray:newData];
}
#end
I call
latestTweets *lt = [[latestTweets alloc] initWithTwitterURL:#"http://search.twitter.com/search.json?q=%23epicwinning+OR+%40charliesheen"];
lt.delegate = self;
Returns result array : -[TwitterFeed returnedArray:]: unrecognized selector sent to instance
Is there any simple tutorial or code sample to fetch both username and hashtag tweets at the same time?
or
Is there a way to fetch also hashtags with MGTwitterEngine ?
Have a look at STTwitter.
STTwitterAPI *twitter =
[STTwitterAPI twitterAPIApplicationOnlyWithConsumerKey:#""
consumerSecret:#""];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *bearerToken) {
[twitter getSearchTweetsWithQuery:#"Snowden"
successBlock:^(NSDictionary *searchMetadata, NSArray *statuses) {
// use the statuses here
} errorBlock:^(NSError *error) {
// ...
}];
} errorBlock:^(NSError *error) {
// ...
}];
You may need to implement your own method below an example source code that works
Try this git
https://bitbucket.org/wave_1102/hdc2010-iphone/src
In your terminal hg clone https://bitbucket.org/wave_1102/hdc2010-iphone type and fetch git.
In HDC2010ViewController replace win with your hashtag
// search twitter for the HDC10 hashtag and add the tweets to our array
[ tweetArray addObjectsFromArray:[ tweetFactory recentTweetsForHashTag:#"win" ] ];
You can use Twitter Kit to display a full timeline in your app (https://docs.fabric.io/ios/twitter/show-timelines.html).
class SearchTimelineViewController: TWTRTimelineViewController {
convenience init() {
let client = TWTRAPIClient()
let dataSource = TWTRSearchTimelineDataSource(searchQuery: "#objc", APIClient: client)
self.init(dataSource: dataSource)
// Show Tweet actions
self.showTweetActions = true
}
}
I have a ViewController declared as:
#interface DownloadViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate>
and I want to use NSURLConnection to download files. NSURLConnection simply "doesn't start", the delegate methods don't work (for example connection:didReceiveResponse is never called) . I noticed in some sample code that the class was subclassing NSObject instead of UIViewController.
How do I combine it? I want to use ViewController methods but then I can't use NSURLConnection.
It's not so easy to find a fully explained example how to download file with NSURLConnection. Everyone only concentrates on the easy methods like didReceiveResponse.
Using a UIViewController instead of an NSObject should not be your problem here !
I'm using a NSURLConnection in an UIViewController with no issue !
Here is a part of my code (not sure it will compile as it is) :
//
// MyViewController.h
//
#import <Foundation/Foundation.h>
#interface MyViewController : UIViewController {
#protected
NSMutableURLRequest* req;
NSMutableData* _responseData;
NSURLConnection* nzbConnection;
}
- (void)loadFileAtURL:(NSURL *)url;
#end
-
//
// MyViewController.m
//
#import "MyViewController.h"
#implementation MyViewController
- (void)loadView {
// create your view here
}
- (void) dealloc {
[_responseData release];
[super dealloc];
}
#pragma mark -
- (void)loadFileAtURL:(NSURL *)url {
// allocate data buffer
_responseData = [[NSMutableData alloc] init];
// create URLRequest
req = [[NSMutableURLRequest alloc] init];
[req setURL:_urlToHandle];
nzbConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
[req release];
req = nil;
}
#pragma mark -
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Append data in the reception buffer
if (connection == nzbConnection)
[_responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (connection == nzbConnection) {
[nzbConnection release];
nzbConnection = nil;
// Print received data
NSLog(#"%#",_responseData);
[_responseData release];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// Something went wrong ...
if (connection == nzbConnection) {
[nzbConnection release];
[_responseData release];
}
}
#end
If you plan to download large files, consider storing the received packets in a file instead of storing it in memory !
If you're having problems, you could consider using the well regarded ASIHTTPRequest library to manage your download. It takes care of everything for you.
For example, just 2 lines will do it.
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:fullPathOfWhereToStoreFile];
Use "NSURLConnection asynchronously" search for the term and you'll find source. Or just NSURLConnection.
For example:
NSURLConnection NSURLRequest proxy for asynchronous web service calls
Using NSURLConnection from apple with example code
Objective-C Programming Tutorial – Creating A Twitter Client Part 1
I'm in the process of trying to move code from a UITableViewController class to a "helper" class.
The code utilizes NSURLConnection to grab and parse JSON and then populate an NSMutableArray.
What I'd like to do is call a method in my helper class that returns a NSMutableArray. What I don't understand is how to return the array from the connectionDidFinishLoading delegate class of NSURLConnection (where the array is actually built) as though it was from the originally called method that started the connection. In other words, how does the method that calls NSURLConnection get control back so it can return a value from the whole operation?
Here are the relevant methods from the helper class. How do I get the getMovies method to return the listOfMovies that is built in the connectionDidFinishLoading delegate class?
-(NSMutableArray)getMovies:(NSURL*)url {
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//NSURLRequest* request = [NSURLRequest requestWithURL: url cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval: 30.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (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 {
//TODO error handling for connection
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//---initialize the array---
listOfMovies = [[NSMutableArray alloc] init];
tmdbMovies = [[NSArray alloc] init];
posters = [[NSArray alloc] init];
thumbs = [[NSDictionary alloc] init];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
SBJsonParser *json = [[SBJsonParser new] autorelease];
tmdbMovies = [json objectWithString:responseString];
// loop through all the top level elements in JSON
for (id movie in tmdbMovies) {
// 0 - Name
// 1 - Meta
// 2 - Url
if ((NSNull *)[movie objectForKey:#"name"] != [NSNull null]) {
if (![[movie objectForKey:#"name"] isEqualToString:#""]) {
name = [movie objectForKey:#"name"];
}
}
if ((NSNull *)[movie objectForKey:#"info"] != [NSNull null]) {
if (![[movie objectForKey:#"info"] isEqualToString:#""]) {
meta = [movie objectForKey:#"info"];
}
}
if ((NSNull *)[movie objectForKey:#"thumb"] != [NSNull null]) {
if (![[movie objectForKey:#"thumb"] isEqualToString:#""]) {
thumbUrl = [movie objectForKey:#"thumb"];
}
}
NSLog(#"Name: %#", name);
NSLog(#"Info: %#", meta);
NSLog(#"Thumb: %#", thumbUrl);
NSMutableArray *movieData = [[NSMutableArray alloc] initWithObjects:name,meta,thumbUrl,nil];
// add movieData array to listOfJMovies array
[listOfMovies addObject:movieData];
[movieData release];
}
//FIXME: Connection warning
if (connection!=nil) {
[connection release];
}
[responseData release];
[responseString release];
}
What you really need to do here is create a #protocol that creates a delegate for your helper class. Then change -(NSMutableArray)getMovies:(NSURL*)url to -(void)getMovies:(NSURL*)url
The class that is calling your helper method needs to implement your helper method's delegate.
Then - (void)connectionDidFinishLoading:(NSURLConnection *)connection calls the delegate method(s). It's best to have a one for success and one for failure.
=Update Begin=
You will need to also define an id delegate in your helper file which the calling class sets to self after init but before calling -(void)getMovies:(NSURL*)url. That way the helper file knows where to call back to.
getMovies *movieListCall = [[getMovies alloc] init];
movieListCall.delegate = self;
[movieListCall getMovies:<your NSURL goes here>];
You will see some additional lines for the inclusion of a delegate in both the getMovies.h and getMovies.m files.
=Update End=
in your getMovies.h file add:
#protocol getMoviesDelegate
#required
- (void)getMoviesSucceeded:(NSMutableArray *)movieArray;
- (void)getMoviesFailed:(NSString *)failedMessage;
#end
#interface getMovies : NSOBject {
id delegate;
}
#property (nonatomic, assign) id delegate;
in your getMovies.m file add:
#synthesize delegate;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//TODO error handling for connection
if ([delegate respondsToSelector:#selector(getMoviesFailed:)]) {
[delegate getMoviesFailed:[error localizedDescription]];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//finishes with
if ([delegate respondsToSelector:#selector(getMoviesSucceeded:)]) {
[delegate getMoviesSucceeded:listOfMovies];
}
}
update your calling class .h file to use getMoviesDelegate:
#interface MoviesView : UIViewController <getMoviesDelegate>{
.
.
.
}
add the getMoviesDelegate methods to your calling class .m file
- (void)getMoviesSucceeded:(NSMutableArray *)movieArray {
//deal with movieArray here
}
- (void)getMoviesFailed:(NSString *)failedMessage {
//deal with failure here
}
This is not tested but hopefully gives you a road map to work with.
Protocols are nice because you can make both required and optional delegate methods and it helps in refining your helper methods to become very reusable across projects. The compiler will also warn you if you have implemented a protocol but not implemented the protocol's required delegate methods. If you follow this path be sure to use conformsToProtocol: and respondsToSelector:
Fundamentally, what's happening is that you're starting an asynchronous network load (asynchronous is the right way to do this, almost assuredly), and then you need some way to resume whatever operation you were doing before the load began. You have a few options:
Create your own delegate protocol. Your UITableViewController would then set itself as the helper's delegate, and the helper would call helperDidLoad or whatever you named that method. There's more information on writing delegates in the Cocoa Programming Guide.
Use blocks and continuation passing style. This is a bit more advanced but I like it. In your UITableViewController you'd write something like this:
[helper doSomething:^ (id loaded) {
[modelObject refresh:loaded]; // or whatever you need to do
}];
And then in your helper you'd write:
- (void)doSomething:(void ^ (id))continuation {
_continuation = continuation;
//kick off network load
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
_continuation(_data);
}
Use notifications. Read the NSNotificationCenter docs.
Use KVO. The KVO programming guide has a lot of good info on Key-Value Observing.
How to i get the getMovies method to return the listOfMovies that is built in the connectionDidFinishLoading delegate class?
I'm going to argue that you should not do that.
Network requests should be made asynchronously. If your getMovies were to make a synchronous request and return only when it had data you would block that entire thread while you waiting for a network connection to finish. This is a bad idea in general and a terrible idea if your main thread is calling getMovies. Blocking the main thread will prevent you from responding to touches or updating the UI, your app will appear frozen, and the OS will terminate it if your users don't quit in frustration first.
Instead have the helper class notify the caller when data is available (or when it failed to retrieve data) through a delegate call back, notification, KVO, or whatever mechanism you prefer.
Here are the steps, pseudocode like style:
[helperInstance setDelegate:self]; // where self is your UITableViewController class
in your helper class, in the connectionDidFinishLoading do something like this:
[delegate finishedLoadingData:JSONData];
Also you can define a protocol for your delegate, and the declare the delegate like this in your helper class:
#property (nonatomic, assign) id<YourProtocol> delegate;
Hope this helps,
Moszi
I am trying to launch the App Store without launching Safari with all the redirects and I am getting an error about "Request for member 'iTunesURL' in something not a structure or union."
I am new to a lot of this so thank you for being patient with me. I think it has something to do with me calling "self.iTunesURL" since it doesn't think iTunesURL is a part of the current class, but I could be very wrong.
Thank you in advance for your help while I am (slowly) learning all of this.
SampleAppDelegate.h
-(void)launchStore:(NSURL *)iTunesURL;
-(void)connectionDidFinishLoading:(NSURLConnection *)connection;
SampleAppDelegate.m
// Process a LinkShare/TradeDoubler/DGM URL to something iPhone can handle
- (void)launchStore:(NSURL *)iTunesURL {
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:iTunesURL] delegate:self startImmediately:YES];
[conn release];
}
// Save the most recent URL in case multiple redirects occur
// "iTunesURL" is an NSURL property in your class declaration
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response {
self.iTunesURL = [response URL];
return request;
}
// No more redirects; use the last URL saved
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[[UIApplication sharedApplication] openURL:self.iTunesURL];
}
MyViewController.h
#import "SampleAppDelegate.h"
and i have NSURL *iTunesURL; within the #interface curley braces.
#property (nonatomic, retain) NSURL *iTunesURL;
- (IBAction) proButtonPressed: (id)sender; // press to launch App Store
MyViewController.m
#import "MyViewController.h"
#implementation MyViewController
#synthesize iTunesURL;
- (IBAction) proButtonPressed: (id) sender {
NSURL *iTunesLink = [NSURL URLWithString:#"actual http URL goes here"];
SampleAppDelegate *appDelegate = (SampleAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate launchStore:iTunesLink];
}
iTunesURL is a property of the ViewController class and you can only use the self reference within the methods of that class. Importing the ViewController.h class doesn't give the SampleAppDelegate class the ability to call the properties of ViewController class unless it is a subclass of ViewController.
You need to create a new another property within SampleAppDelegate and assign the value of ViewController.iTunesURL to that property.
I have reviewed similar stackoverflow questions/answers to this but I am still stumped.
I'm a beginner and I'm really struggling with this. With the iPhone, I can download XML from a URL but I cannot store the result string in a NSString variable and see it from the calling function.
I have the following declarations in a custom made class:
#interface comms : NSObject {
NSString *currURL, *receivedString;
NSMutableData *receivedData;
NSURLConnection *conn;
}
#property (copy, readwrite) NSString *currURL;
#property (copy, readonly) NSString *receivedString;
#property (nonatomic, assign) NSMutableData *receivedData;
#property (nonatomic, assign) NSURLConnection *conn;
-(void) getContentURL;
I have the following method in the comms class:
-(void) getContentURL
{
NSLog( #"Begin getContentURL." );
// Request data related.
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init]
autorelease];
[request setURL:[NSURL URLWithString: currURL]];
// Content-Type related.
[request setValue:#"application/x-www-form-urlencoded"
forHTTPHeaderField:#"Content-Type"];
// Create Connection.
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn) {
// The connection was established.
receivedData = [[NSMutableData data] retain];
NSLog( #"Data will be received from URL: %#", request.URL );
}
else
{
// The download could not be made.
NSLog( #"Data could not be received from: %#", request.URL );
}
// PROBLEM - receivedString is NULL here.
NSLog( #"From getContentURL: %#", receivedString );
}
I have created the required delegates in the comms class as per the following:
-(void)connection:(NSURLConnection *)connection didReceiveResponse:
(NSURLResponse *)response
{
// Discard all previously received data.
[receivedData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:
(NSData *)data
{
// Append the new data to the receivedData.
[receivedData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Connection succeeded in downloading the request.
NSLog( #"Succeeded! Received %d bytes of data", [receivedData length] );
// Convert received data into string.
receivedString = [[NSString alloc] initWithData:receivedData
encoding:NSASCIIStringEncoding];
NSLog( #"From connectionDidFinishLoading: %#", receivedString );
// release the connection, and the data object
[conn release];
[receivedData release];
}
I can successfully output the receivedString string using NSLog in the connectionDidFinishLoading delegate.
// Convert received data into string.
receivedString = [[NSString alloc] initWithData:receivedData
encoding:NSASCIIStringEncoding];
NSLog( #"From connectionDidFinishLoading: %#", receivedString );
However, when I output the receivedString string in the getContentURL it's null (and hence is also null from the ViewController.m class which I call the comms class from).
// PROBLEM - receivedString is NULL here.
NSLog( #"From getContentURL: %#", receivedString );
Any ideas on how I can see the value of receivedString in getContentURL and from the ViewController.m class?
NSURLConnection is an asynchronous API. When you start the request, the object will spawn a new thread, and only update your main one via the callback/delegate methods. Your current method will return most likely before the request is finished, and so the string of the result will not have downloaded yet!
If you want to do this synchronously, you will have two options:
Use the built in synchronous download method. Note that as this blocks, it will not allow the user to interact with the UI.
Use the C functions CFRunLoopRun() and CFRunLoopStop() to start the run loop inside your calling function, wait until the download is complete or failed, then return control back to the calling method with CFRunLoopStop().
To return data from the delegates method, please use Code Block.
See Apple's Blocks documentation.