load data from cache with NSURL doesn't work - objective-c

i'm trying to load a photo from my cache directory.
this is the code where i write the photo into a cache folder:
+(BOOL)writeAData:(NSData *)imageData atURL:(NSURL *)fileUrl
{
return [imageData writeToURL:fileUrl atomically:YES];
}
this code works fine, but i have problems when i try to load the code from the cache folders:
i use the method initWithContentsOfURL inside a block:
NSData *imageData = [[NSData alloc] initWithContentsOfURL:self.imageUrl];
this is the format of url
file://localhost/Users/MarcoMignano/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/0E8E54D8-9634-41CF-934B-A7315411F12F/Library/Caches/image_cache/Meyer%20Library.jpg
the URL is correct, but when i try to use the method above i get this error:
..... [__NSCFString isFileURL]: unrecognized selector sent to instance 0x8a0c5b0 .....
that is the code when i take the url of my model:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
self.photos = [PhotoAlreadyDisplayed getAllPicture];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([sender isKindOfClass:[UITableViewCell class]]) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
if (indexPath) {
if ([segue.identifier isEqualToString:#"Show Image"]) {
if ([segue.destinationViewController respondsToSelector:#selector(setImageUrl:)]) {
NSURL *url = [[self.photos objectAtIndex:indexPath.row] valueForKey:#"url"];
[segue.destinationViewController performSelector:#selector(setImageUrl:) withObject:url];
[segue.destinationViewController setTitle:[self titleForRow:indexPath.row]];
}
}
}
}
}
whats wrong with the URL? how can i fix it? thank you
i have find the solution:
when i load the url for the model, i need to initialize the url using fileURLWithPath method:
NSURL *url = [NSURL fileURLWithPath:[[self.photos objectAtIndex:indexPath.row] valueForKey:#"url"]];
Now all works fine, thank you so much for yours help

[NSData initWithContentsOfURL:] is expecting an NSURL as the argument passed in. It looks like you might be passing in a string, rather than an NSURL. Is this the case?
EDIT: Just humour me - try replacing
NSData *imageData = [[NSData alloc] initWithContentsOfURL:self.imageUrl];
with
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:self.imageUrl]];
What happens?
Though it doesn't look like you're returning successfully from initWithContentsOfURL:, but the snippet below may be of use to others:
NSError *error;
NSData *data = [[NSData alloc] initWithContentsOfURL:TestURL options:0 error:&error];
if(data) {
NSLog(#"Success");
}
else {
NSLog(#"Failed: %#", Error);
}

solution: when i load the url for the model, i need to initialize the url using fileURLWithPath method:
NSURL *url = [NSURL fileURLWithPath:[[self.photos objectAtIndex:indexPath.row] valueForKey:#"url"]];
Now all works fine, thank you so much for yours help

Related

slow loading using initWithContentsOfUrl

I have a web service and I make HTTP calls to it from cocoa using this line of code:
NSData *imageData = [[NSData alloc] initWithContentsOfUrl:url options: NSDataReadingUncached error:&error];
Sometimes is it take 10 seconds, sometimes 30 seconds to load the picture from this URL.
I tried loading this URL from a normal browser and it takes 1-2 seconds.
I'm doing lazy loading and the problem is the time it takes to load the contents of this URL vs a normal browser. Both tests were done from the same network.
Download.m
NSError *error;
NSData *imageData = [[NSData alloc] initWithContentsOfURL:self.photoRecord.URL options:NSDataReadingUncached error:&error];
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData:imageData options:NSJSONReadingAllowFragments error:&myError];
NSMutableDictionary *pictureInfo = [jsonArray objectAtIndex:0];
NSString *picture;
picture = [pictureInfo valueForKey:#"Picture"];
NSData *base64Data = [[NSData alloc]initWithBase64Encoding:picture];
if (base64Data) {
UIImage *downloadedImage = [UIImage imageWithData:base64Data];
self.photoRecord.image = downloadedImage;
}
[(NSObject *)self.delegate performSelectorOnMainThread:#selector(imageDownloaderDidFinish:) withObject:self waitUntilDone:NO];
Then on the main thread PictureController.m:
-(void) loadScrollViewWithPage:(NSUInteger)page{
....
NSIndexPath *myIndexPath = [NSIndexPath indexPathForRow:page inSection:0];
[self startOperationsForPhotoRecord:aRecord atIndexPath:myIndexPath];
}
- (void)startOperationsForPhotoRecord:(PictureRecord *)record atIndexPath:(NSIndexPath *)indexPath {
Download *imageD = [[Download alloc] initWithPhotoRecord:record atIndexPath:indexPath delegate:self];
[self.pendingOperations.downloadsInProgress setObject:imageD forKey:indexPath];
[self.pendingOperations.downloadQueue addOperation:imageD];
}
Then I have the delegate method to update the UIImageView when the download is done which is working just fine.
The size of the content being loaded is around 400kb.
Any ideas?

xcode async tableview load image move listview images gone

We want to download image and data async to our tableview and we want to cache it not to download it again. We found a code for caching.Here is our code. It works asynchronously but when we scroll table view, images gone and come back(we cant see image for a while). Sometimes wrong image come to wrong cell. What might be the reasons and how can we solve it ?
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#",[userInfo[0] serverUrl],[estateList[indexPath.row] imgUrl]]];
NSString *key = [imageURL absoluteString];
NSData *data = [FTWCache objectForKey:key];
if (data) {
UIImage *image = [UIImage imageWithData:data];
cell.imageView.image = image;
} else {
cell.imageView.image = [UIImage imageNamed:#"yukleniyor"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:imageURL];
[FTWCache setObject:data forKey:key];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = image;
});
});
}
Here is that code we found for caching
Header is like this
#import <Foundation/Foundation.h>
#interface FTWCache : NSObject
+ (void) resetCache;
+ (void) setObject:(NSData*)data forKey:(NSString*)key;
+ (id) objectForKey:(NSString*)key;
#end
And .m file is like this
#import "FTWCache.h"
static NSTimeInterval cacheTime = (double)604800;
#implementation FTWCache
+ (void) resetCache {
[[NSFileManager defaultManager] removeItemAtPath:[FTWCache cacheDirectory] error:nil];
}
+ (NSString*) cacheDirectory {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
cacheDirectory = [cacheDirectory stringByAppendingPathComponent:#"FTWCaches"];
return cacheDirectory;
}
+ (NSData*) objectForKey:(NSString*)key {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filename = [self.cacheDirectory stringByAppendingPathComponent:key];
if ([fileManager fileExistsAtPath:filename])
{
NSDate *modificationDate = [[fileManager attributesOfItemAtPath:filename error:nil] objectForKey:NSFileModificationDate];
if ([modificationDate timeIntervalSinceNow] > cacheTime) {
[fileManager removeItemAtPath:filename error:nil];
} else {
NSData *data = [NSData dataWithContentsOfFile:filename];
return data;
}
}
return nil;
}
+ (void) setObject:(NSData*)data forKey:(NSString*)key {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filename = [self.cacheDirectory stringByAppendingPathComponent:key];
BOOL isDir = YES;
if (![fileManager fileExistsAtPath:self.cacheDirectory isDirectory:&isDir]) {
[fileManager createDirectoryAtPath:self.cacheDirectory withIntermediateDirectories:NO attributes:nil error:nil];
}
NSError *error;
#try {
[data writeToFile:filename options:NSDataWritingAtomic error:&error];
}
#catch (NSException * e) {
//TODO: error handling maybe
}
}
#end
Sorry for my previous answer.
I will try to explain the problem:
We have TableView total number of rows and rows of the reserved area of the display. As a result, images with asynchronous load can not be loaded into their cells (because it is inserted as it downloads from the memory).
The solution is very simple, you must assign each ImageView with key and this key associated with the cells of the table.
I resolve this problem by using code from this git (https://gist.github.com/khanlou/4998479)
There are two files on it
UIImageView+Network.h
UIImageView+Network.m
You must include they in your project, or create own class and paste to it.
This class uses FTW/FTWCache from (https://github.com/FTW/FTWCache/tree/master/FTWCache). So you must add to your project this one too.
After that you must to import
#import "UIImageView+Network.h"
in file which will use asynchronous image loading and caching.
And short part of code with TableView using
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"MyTableCell";
MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil){
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// construction to call method
// [cell.imageView loadImageFromURL:(NSURL*)url placeholderImage:(UIImage*)placeholder cachingKey:(NSString*)key ];
[cell.thumbnailImageView loadImageFromURL:(NSURL*)url placeholderImage:[UIImage imageNamed:#"no_foto.gif"] cachingKey:(NSString*)[NSString stringWithFormat:#"%d",indexPath.row]];
return cell;
}

iOS Read Json from web and display to tableView

What I am trying to do is read a json file on the web (I know the connection to this aspect is working) and then get some file contents to display on my tableView.
I was able to do this fine in another example but I'm not sure what the problem is now.
JSON File:
{
"entry":
[
{"Current Date":"Tuesday June 22 2011","Time Period":"00:00 - 06:45,"},
{"Current Date":"Tuesday June 23 2011","Time Period":"00:00 - 07:22"}
]
}
Button that fetches the JSON file from the web:
- (IBAction)getJsonButton:(id)sender {
[array removeAllObjects];
NSURL *url = [NSURL URLWithString:#"https://LinkToWhereJSONfileIsLocated/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
connection = [NSURLConnection connectionWithRequest:request delegate:self];
if(connection)
{
webData = [[NSMutableData alloc]init];
}
}
Here's where I think I'm having my problem (must be my logic or syntax):
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
NSArray *arrayOfEntry = [allDataDictionary objectForKey:#"entry"];
for (NSDictionary *diction in arrayOfEntry) {
NSString *currDate = [diction objectForKey:#"Current Date"];
[array addObject:currDate];
}
[[self myTableView]reloadData];
}
This is a quick guess, try calling reloadData method on main thread.

Objective C - attachments via MFMailComposeViewController not showing up

I'm trying to attach a wav-file from an iOS application but the attachment is not delivered even though it's visible in the composed mail.
Heres the related code:
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:NSLocalizedString(#"mailTopic", nil)];
[controller setMessageBody:NSLocalizedString(#"mailBody", nil) isHTML:YES];
NSString *wavPath = [self exportAssetAsWaveFormat:self.myRec.soundFilePath]; // CAF->Wav export
if (wavPath != nil) {
NSLog(#"wavPath: %#", wavPath);
NSData *recData = [NSData dataWithContentsOfFile:wavPath];
NSString *mime = [self giveMimeForPath:wavPath];
[controller addAttachmentData:recData mimeType:mime fileName:#"MySound.wav"];
[self presentModalViewController:controller animated:YES];
[controller release];
}
}
-(NSString *) giveMimeForPath:(NSString *)filePath {
NSURL* fileUrl = [NSURL fileURLWithPath:filePath];
NSURLRequest* fileUrlRequest = [[NSURLRequest alloc] initWithURL:fileUrl cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:.1];
NSURLResponse* response = nil;
[NSURLConnection sendSynchronousRequest:fileUrlRequest returningResponse:&response error:nil];
NSString* mimeType = [response MIMEType];
NSLog(#"MIME: %#", mimeType);
[fileUrlRequest release];
return mimeType;
}
NSLog results:
NSLog(#"wavPath: %#", wavPath); -> "wavPath: /var/mobile/Applications/71256DCA-9007-4697-957E-AEAE827FD97F/Documents/MySound.wav"
NSLog(#"MIME: %#", mimeType); -> "MIME: audio/wav"
The file path seams to be ok (see NSLog data), and the mime type set to "audio/wav".. Cant figure this out..
The error was that the wav-file was not 100% written by the time I create NSData out of it.. duuuh
Thanks for the effort guys
Maybe the destination is stripping attachments of that type? Did you try manually sending a message with a .wav and see if it works? I had the same problem trying to send to Zendesk. Turns out they strip attachments for some mimetypes.

Obj C UIWebView with Variable URL Search Query

How do you use a URL and be able to change part of the URL? I'm new at Objective C.
Errors at url in all spots!
restaurants is my UIWebView, zip is my UITextField, restlabel is my UILabel.
-(void)load {
url = [[NSString alloc] initWithFormat:#"http://www.example.com/search?query=%#", restlabel.text];
}
-(IBAction)gourl {
restlabel.text = [NSString stringWithFormat:#"%#", [zip text]];
[restaurants loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
}
You have to read the text from the text field and build the URL in your gourl method, not in the load method.
-(IBAction)goToURL {
url = [[NSString alloc] initWithFormat:#"http://www.example.com/search?query=%#", restlabel.text];
[restaurants loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
}
You can't define a string with a placeholder that will be dynamically changed (I think that was what you were trying to do). You build a string with a "snapshot" of the variables you are referencing.
Found my own answer.
-(IBAction)gorest {
restlabel.text = [NSString stringWithFormat:#"%#", [zip text]];
NSString *url;
url = [[NSString alloc] initWithFormat:#"http://maps.google.com/maps?q=Restaurants+in+%#", restlabel.text];
[restaurants loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
next.hidden = NO;
}