Weird NSString vs NSURL behavior - iphone

I have a class which parse an XML feed. In that class I have to following method:
-(id)loadXMLByURL:(NSString *)urlString name:(NSString*)name{
NSString *urls = [[NSString alloc]initWithFormat:#"%#%#" , urlString, name];
NSLog(#"STRING URL: %#" , urls);
NSURL *url = [NSURL URLWithString:urls];
NSLog(#"%#" , url);
parser = [[NSXMLParser alloc]initWithContentsOfURL:url];
parser.delegate = self;
BOOL success = [parser parse];
if (success) {
NSLog(#"No error");
}else{
NSLog(#"Error: %#" , parser.parserError);
}
return self;
}
The first NSLog is the correct url, however the NSURL comes out as (null)
Here's where I call the method:
//f is an object where I store the value of name from another feed, which I have to use as a parameter in the url for this feed
NSString *name = f.name;
myParser = [[MyParser alloc]loadXMLByURL:#"http://myurl.com/names.asp?name=" name:name];
If I NSLog name here, it shows the right value.
Anyone have any idea why the NSURL comes out as (null)?

You'll want to escape name.
Add a category on NSString and then call [name urlEncodedString]. e.g.:
#implementation NSString (URLEncoding)
- (NSString *)urlEncodedString
{
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
kCFStringEncodingUTF8);
}
#end

Use the following..
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat::#"%#%#" , urlString, name]]];
parser = [[NSXMLParser alloc] initWithData: data];
parser.delegate = self;
BOOL success = [parser parse];
if (success) {
NSLog(#"No error");
}else{
NSLog(#"Error: %#" , parser.parserError);
}
return self;

Related

UITextField and NSURL URLWithString

I have built a translate application in ios. The application uses the Yandex translation api. I followed this tutorial: http://www.raywenderlich.com/5492/working-with-json-in-ios-5
My ViewController.m looks like this (I took out my api key):
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1
#import "ViewController.h"
#end
#interface NSDictionary(JSONCategories)
+(NSDictionary*)dictionaryWithContentsOfJSONURLString:(NSString*)urlAddress;
-(NSData*)toJSON;
#end
#implementation NSDictionary(JSONCategories)
+(NSDictionary*)dictionaryWithContentsOfJSONURLString:(NSString*)urlAddress
{
NSData* data = [NSData dataWithContentsOfURL: [NSURL URLWithString: urlAddress] ];
__autoreleasing NSError* error = nil;
id result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error != nil) return nil;
return result;
}
-(NSData*)toJSON
{
NSError* error = nil;
id result = [NSJSONSerialization dataWithJSONObject:self options:kNilOptions error:&error];
if (error != nil) return nil;
return result;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
// NSData* data = [[NSData dataWithContentsOfURL: TranslateText] ];
NSData*data = [NSURL URLWithString: [NSString stringWithFormat: #"https://translate.yandex.net/api/v1.5/tr.json/translate?key=apikeys&lang=en-es&text=%#", textfield.text]];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* TranslatedText = [json objectForKey:#"text"]; //2
NSLog(#"Text that was translated: %#", TranslatedText); //3
// 1) Get the latest loan
//NSDictionary* ttext = [TranslatedText objectAtIndex:0];
NSString* ttext = [TranslatedText objectAtIndex:0];
// 3) Set the label appropriately
humanReadble.text = [NSString stringWithFormat:#"%#",
//[ttext objectForKey:#"name"],
ttext];
}
#end`
When I run the app, I get the error Thread 1: signal SIGABRT on this line of code:
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
What should I do?
The error in your code is the use of the colon there. You should have the line be...
[NSURL URLWithString: [NSString stringWithFormat: #"https://translate.yandex.net/api/v1.5/tr.json/translate?apikeyes&text=%#", textfield.text];
Also, I do not know why you would do a #define. Grab the information in the method for handling the button getting pressed.
NSURL * translateURL = [NSURL URLWithString: [NSString stringWithFormat: #"https://translate.yandex.net/api/v1.5/tr.json/translate?apikeyes&text=%#", textfield.text];

Xcode Parse Json Data

My code below was working, before, but suddenly it stopped working. Could anyone tell me what I'm doing wrong?
Output of NSLog():
2013-05-14 16:06:35.475 Run.PH[1502:19a03] background = (null)
2013-05-14 16:06:35.476 Run.PH[1502:19a03] logo = (null)
2013-05-14 16:06:35.476 Run.PH[1502:19a03] json = (null)
2013-05-14 16:06:35.476 Run.PH[1502:19a03] welcome = (null)
Codes:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *urlString = [NSString stringWithFormat:#"http://run.ph/json/test_json_dyna.jsp"];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
if(data != nil)
{
NSError *error;
_json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
_welcomeMessage.text = [[_json objectForKey:#"welcome"] objectForKey:#"message"];
NSString *background = [[_json objectForKey:#"welcome"] objectForKey:#"background"];
NSString *logo = [[_json objectForKey:#"welcome"] objectForKey:#"logo"];
NSLog(#"background = %#", background);
NSLog(#"logo = %#", logo);
NSLog(#"json = %#", _json);
NSLog(#"welcome = %#", _welcomeMessage.text);
NSURL *urlBackground = [NSURL URLWithString:background];
NSData *dataBackground = [NSData dataWithContentsOfURL:urlBackground];
[_background setImage:[UIImage imageWithData:dataBackground]];
NSURL *urlLogo = [NSURL URLWithString:logo];
NSData *dataLogo = [NSData dataWithContentsOfURL:urlLogo];
[_logo setImage:[UIImage imageWithData:dataLogo]];
}
else
{
NSLog(#"Error!");
}
[self.view reloadInputViews];
}
Just NSLog your URL response you will get wats wrong with your json.
Try this
NSString *respo = [NSString stringWithContentsOfURL:[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
NSLog(#"Response - %#",respo);
It has return "\r" and newline character "\n" with your response.
Check this
EDIT
Now your URL is working fine, problem was with your web service end.

Load Web-Content Asynchronously

I am trying to load web content asynchronously. I have a large amount of web calls in my viewdidappear method and my app is very unresponsive. I understand the concepts of synchronous and asynchronous loading of content, but don't know how to tell if this is being done asynchronously. The code below is simply embedded in my viewdidappear method, and I assume it is loading synchronously. How would I edit this to make it load asynchronously? Thank you all!
NSString *strURLtwo = [NSString stringWithFormat:#"http://website.com/json.php?
id=%#&lat1=%#&lon1=%#",id, lat, lon];
NSData *dataURLtwo = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURLtwo]];
NSArray *readJsonArray = [NSJSONSerialization JSONObjectWithData:dataURLtwo options:0
error:nil];
NSDictionary *element1 = [readJsonArray objectAtIndex:0];
NSString *name = [element1 objectForKey:#"name"];
NSString *address = [element1 objectForKey:#"address"];
NSString *phone = [element1 objectForKey:#"phone"];
You can use NSURLConnectionDelegate:
// Your public fetch method
-(void)fetchData
{
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://website.com/json.php?id=%#&lat1=%#&lon1=%#",id, lat, lon]];
// Put that URL into an NSURLRequest
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
// Create a connection that will exchange this request for data from the URL
connection = [[NSURLConnection alloc] initWithRequest:req
delegate:self
startImmediately:YES];
}
Implement the delegate methods:
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
// Add the incoming chunk of data to the container we are keeping
// The data always comes in the correct order
[jsonData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
// All data is downloaded. Do your stuff with the data
NSArray *readJsonArray = [NSJSONSerialization jsonData options:0 error:nil];
NSDictionary *element1 = [readJsonArray objectAtIndex:0];
NSString *name = [element1 objectForKey:#"name"];
NSString *address = [element1 objectForKey:#"address"];
NSString *phone = [element1 objectForKey:#"phone"];
jsonData = nil;
connection = nil;
}
// Show AlertView if error
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
connection = nil;
jsonData = nil;
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#", [error localizedDescription]];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
}
For asynchronous web content loading, I recommend you to use AFNetworking . It'll solve lots of your major headache of networking in future. How to do:
1) subclass AFHTTPCLient, for example:
//WebClientHelper.h
#import "AFHTTPClient.h"
#interface WebClientHelper : AFHTTPClient{
}
+(WebClientHelper *)sharedClient;
#end
//WebClientHelper.m
#import "WebClientHelper.h"
#import "AFHTTPRequestOperation.h"
NSString *const gWebBaseURL = #"http://whateverBaseURL.com/";
#implementation WebClientHelper
+(WebClientHelper *)sharedClient
{
static WebClientHelper * _sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:gWebBaseURL]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self registerHTTPOperationClass:[AFHTTPRequestOperation class]];
return self;
}
#end
2) Request asynchronously your web content, put this code in any relevant part
NSString *testNewsURL = #"http://whatever.com";
NSURL *url = [NSURL URLWithString:testNewsURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operationHttp =
[[WebClientHelper sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *szResponse = [[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"Response: %#", szResponse );
//PUT your code here
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Operation Error: %#", error.localizedDescription);
}];
[[WebClientHelper sharedClient] enqueueHTTPRequestOperation:operationHttp];

parserDidEndDocument not getting called

parserDidNotEndDocument does not get called, it was working yesterday, the only thing that i think is different is i am using xcode 4 now. error getting thrown is Error on XML Parse: The operation couldn’t be completed. (NSXMLParserErrorDomain error 5.)
#implementation profileViewController
#synthesize userArray;
#synthesize userData;
#synthesize userId;
#synthesize gender;
#synthesize nameIB;
#synthesize numberIB;
#synthesize loginButton;
#synthesize logoutButton;
#synthesize activityIndicator;
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
-(IBAction)textDone:(id)sender
{
[sender resignFirstResponder];
}
-(IBAction)genderSelection:(id)sender
{
if([sender selectedSegmentIndex] == kSwitchesSegmentIndex)
{
gender = #"Male";
//NSLog(gender);
}
else {
gender = #"Female";
//NSLog(gender);
}
}
-(IBAction)postData:(id)sender
{
loginButton.hidden = YES;
loginButton.enabled = NO;
if(nameIB.text.length && numberIB.text.length > 0)
{
//[self performSelectorInBackground:#selector(sendData) withObject:nil];
NSMutableData *data = [NSMutableData data];
NSString *number = numberIB.text;
NSString *name = nameIB.text;
NSString *nameString = [[NSString alloc] initWithFormat:#"name=%#", name];
NSString *numberString = [[NSString alloc] initWithFormat:#"&number=%#", number];
NSString *genderString = [[NSString alloc] initWithFormat:#"&gender=%#", gender];
//NSLog(nameString);
//NSLog(numberString);
[data appendData:[nameString dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[numberString dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[genderString dataUsingEncoding:NSUTF8StringEncoding]];
NSURL *url = [NSURL URLWithString:#"http://www.blah.net/test.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:data];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSLog(#"responseData: %#", responseData);
userData = responseData;
logoutButton.hidden = NO;
logoutButton.enabled = YES;
[self startParsingUserId];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Text Fields Empty" message:#"One Or More Textfields Are Empty" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
loginButton.enabled = YES;
loginButton.hidden = NO;
logoutButton.enabled = NO;
}
}
/*-(void)sendData
{
[activityIndicator startAnimating];
NSMutableData *data = [NSMutableData data];
NSString *number = numberIB.text;
NSString *name = nameIB.text;
NSString *nameString = [[NSString alloc] initWithFormat:#"name=%#", name];
NSString *numberString = [[NSString alloc] initWithFormat:#"&number=%#", number];
NSString *genderString = [[NSString alloc] initWithFormat:#"&gender=%#", gender];
//NSLog(nameString);
//NSLog(numberString);
[data appendData:[nameString dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[numberString dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[genderString dataUsingEncoding:NSUTF8StringEncoding]];
NSURL *url = [NSURL URLWithString:#"http://www.blah.net/test.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:data];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSLog(#"responseData: %#", responseData);
userData = responseData;
}*/
-(IBAction)logout:(id)sender
{
NSString *userID = self.userId;
NSMutableData *data = [NSMutableData data];
NSMutableString *userString = [[NSMutableString alloc] initWithFormat:#"id=%#", userID];
//NSLog(userString);
//NSLog(numberString);
[data appendData:[userString dataUsingEncoding:NSUTF8StringEncoding]];
NSURL *url = [NSURL URLWithString:#"http://www.blah.net/offline.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:data];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSLog(#"responseData: %#", responseData);
loginButton.hidden = NO;
logoutButton.hidden = YES;
loginButton.enabled = YES;
logoutButton.enabled = NO;
}
-(void)startParsingUserId
{
NSLog(#"parsing init");
NSXMLParser *idParser = [[NSXMLParser alloc] initWithData:userData]; //uses the NSMutableData data type to parse
idParser.delegate = self; //set the delegate to this viewControlelr
[idParser parse];
[idParser release];
}
-(void)parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(#"parsing started");
currentElementName = nil;
currentText = nil;
}
//this is called for each xml element
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
//NSLog(#"started element");
if ([elementName isEqualToString:#"usercallback"]) //if elementName == status then start of new tweet so make new dictionary
{
[currentIDDict release];
currentIDDict = [[NSMutableDictionary alloc] initWithCapacity:[interestingTags count]]; //make dictionary with two sections
}
else if([interestingTags containsObject:elementName]) //if current element is one stored in interesting tag, hold onto the elementName and make a new string to hold its value
{
currentElementName = elementName; //hold onto current element name
currentText = [[NSMutableString alloc] init];
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(#"appending");
[currentText appendString:string];
}
//after each element it goes back to the parent after calling this method
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:currentElementName])
{
[currentIDDict setValue: currentText forKey: currentElementName];
}
else if([elementName isEqualToString:#"usercallback"])
{
[self.userArray addObject:currentIDDict];
}
NSLog(#"ending");
currentText = nil;
[currentText release];
}
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(#"end");
NSDictionary *rowData = [self.userArray objectAtIndex:0];
userId = [[NSString alloc] initWithFormat:#"%#", [rowData objectForKey:#"id"]];
NSLog(#"DONE PARSING DOCUMENT");
NSLog(#"userid = %#", userId);
}
Solution for finding parse error:
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSDictionary *userInfo = parseError.userInfo;
NSNumber *lineNumber = userInfo[#"NSXMLParserErrorLineNumber"];
NSNumber *errorColumn = userInfo[#"NSXMLParserErrorColumn"];
NSString *errorMessage = userInfo[#"NSXMLParserErrorMessage"];
NSLog(#"Error occured in line %# and column %#\nWith message: %#", lineNumber, errorColumn, errorMessage);
}

iOS: Download image from url and save in device

I am trying to download the image from the url http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg
I am using the following code, but image is not saved in the device. I want to know what I am doing wrong.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
[NSURLConnection connectionWithRequest:request delegate:self];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:#"pkm.jpg"];
NSData *thedata = NULL;
[thedata writeToFile:localFilePath atomically:YES];
UIImage *img = [[UIImage alloc] initWithData:thedata];
I happen to have exactly what you are looking for.
Get Image From URL
-(UIImage *) getImageFromURL:(NSString *)fileURL {
UIImage * result;
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
result = [UIImage imageWithData:data];
return result;
}
Save Image
-(void) saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
if ([[extension lowercaseString] isEqualToString:#"png"]) {
[UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"png"]] options:NSAtomicWrite error:nil];
} else if ([[extension lowercaseString] isEqualToString:#"jpg"] || [[extension lowercaseString] isEqualToString:#"jpeg"]) {
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"jpg"]] options:NSAtomicWrite error:nil];
} else {
NSLog(#"Image Save Failed\nExtension: (%#) is not recognized, use (PNG/JPG)", extension);
}
}
Load Image
-(UIImage *) loadImage:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#.%#", directoryPath, fileName, extension]];
return result;
}
How-To
//Definitions
NSString * documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//Get Image From URL
UIImage * imageFromURL = [self getImageFromURL:#"http://www.yourdomain.com/yourImage.png"];
//Save Image to Directory
[self saveImage:imageFromURL withFileName:#"My Image" ofType:#"png" inDirectory:documentsDirectoryPath];
//Load Image From Directory
UIImage * imageFromWeb = [self loadImage:#"My Image" ofType:#"png" inDirectory:documentsDirectoryPath];
If you set theData to nil, what do you expect it to write to the disk?
What you can use is NSData* theData = [NSData dataWithContentsOfURL:yourURLHere]; to load the data from the disk and then save it using writeToFile:atomically:. If you need more control over the loading process or have it in background, look at the documentation of NSURLConnection and the associated guide.
This is the code to download the image from url and save that image in the device and this is the reference link.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
[NSURLConnection connectionWithRequest:request delegate:self];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:#"pkm.jpg"];
NSData *thedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
[thedata writeToFile:localFilePath atomically:YES];
Get Image From URL
-(UIImage *) getImageFromURL:(NSString *)fileURL {
UIImage * result;
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
result = [UIImage imageWithData:data];
return result;
}
This worked great for me but I ran into memory issues with CFData (store). Fixed it with an autoreleasepool:
-(UIImage *) getImageFromURL:(NSString *)fileURL {
#autoreleasepool {
UIImage * result;
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
result = [UIImage imageWithData:data];
return result;
}
}
Since we are on IOS6 now, you no longer need to write images to disk neccessarily.
Since iOS5 you are now able to set "allow external storage" on an coredata binary attribute.
According to apples release notes it means the following:
Small data values like image thumbnails may be efficiently stored in a
database, but laarge photos or other media are best handled directly by
the file system. You can now specify that the value of a managed
object attribute may be stored as an external record - see setAllowsExternalBinaryDataStorage:
When enabled, Core Data heuristically decides on a per-value basis if
it should save the data directly in the database or store a URI to a
separate file which it manages for you. You cannot query based on the
contents of a binary data property if you use this option.
Hi It is clear that you are writing NULL data to your file.
In your code statement NSData *thedata = NULL; indicates that you assign NULL value to your data.
You are writing NULL data to your file as well.
Please check your code once again.
-(IBAction)BtnDwn:(id)sender
{
[self.actvityIndicator startAnimating];
NSURL *URL = [NSURL URLWithString:self.dataaArray];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
{
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath];
NSURL *documentURL = [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:[documentURL path]];
if (exists)
{
NSLog(#"not created");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Download"
message:#"sory,file already exists"
delegate:nil
cancelButtonTitle:#"cancel"
otherButtonTitles:nil];
[alert show];
}
else
{
[[NSFileManager defaultManager] moveItemAtURL:location toURL:documentURL error:nil];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Download"
message:#"Succesfully downloaded"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[self.actvityIndicator stopAnimating];
NSLog(#"wait downloading......");
[alert show];
}
}];
[downloadTask resume];
}
Here is how you can save an image asynchronously in Swift:
requestImage("http://www.asdf.com/89asdf.gif") { (image) -> Void in
let myImage = image
}
func requestImage(url: String, success: (UIImage?) -> Void) {
requestURL(url, success: { (data) -> Void in
if let d = data {
success(UIImage(data: d))
}
})
}
func requestURL(url: String, success: (NSData?) -> Void, error: ((NSError) -> Void)? = nil) {
NSURLConnection.sendAsynchronousRequest(
NSURLRequest(URL: NSURL (string: url)!),
queue: NSOperationQueue.mainQueue(),
completionHandler: { response, data, err in
if let e = err {
error?(e)
} else {
success(data)
}
})
}
Its included as a standard function in my repo:
https://github.com/goktugyil/EZSwiftExtensions
Here's an example of how I download banners to my app. I download the images in the background, and most of my apps do not use reference counting so I release objects.
- (void)viewDidLoad {
[super viewDidLoad];
[NSThread detachNewThreadSelector:#selector(loadImageInBackground) toTarget:self withObject:nil];
}
- (void) loadImageInBackground {
NSURL *url = [[NSURL alloc] initWithString:#"http://yourImagePath.png"];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
[url release];
UIImage *result = [[UIImage alloc] initWithData:data];
[data release];
UIImageView *banner_ImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
[self.view addSubview:banner_ImageView];
banner_ImageView.image = result;
[result release];
}