iOS image resolution issue - iphone

In My project I am using image view which downloads image from server. It is working fine on iOS 4 but it is not showing on iOS 5.
Is there any minimum resolution needs to be take care while using iOS 5. One of image which comes from server is of 72 dpi resolution which works on iOS 4 but not on iOS 5.
I have written category to image view which will download code from image URL
Here is code snippet:
- (void) setImageFromServer:(NSString *) imageURL
{
if (imageURL!=nil)
{
ImageDownloader *imageDownloader = [[[ImageDownloader alloc] init] autorelease];
imageDownloader.requester = self;
[imageDownloader startDownload:imageURL];
}
}
- (void) didDownloadImageData:(NSData *) data forImageURL:(NSString *) imageURL
{
[self setImage:[UIImage imageWithData:data]];
}
In downloader file :
- (void) startDownload:(NSString *)MyimageURL {
self.imageData = [NSMutableData data];
self.currentImageURL = MyimageURL;
self.downloadConnection = [NSURLConnection connectionWithRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:self.currentImageURL]]
delegate: self];
[self.downloadConnection start];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[imageData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[self.requester didDownloadImageData:self.imageData forImageURL:self.currentImageURL];
isRewardTagImageAvailable = YES;
[connection release];
connection = nil;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
}

I am not sure if this is a problem, but usually when I am writing a NSURLRequest I first initialize things as follows and the insert the request into a NSURLConnection. Sort of like this. Also note that once you initWithRequst in a NSURLConnection, you do not have to tell that connection to start, it will automatically.
NSURLRequest *tempReq = [[NSURLRequest alloc] initWithURL:someURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
NSURLConnection *tempCon = [[NSURLConnection alloc] initWithRequest:tempReq delegate:self];
I mean it should not matter, but give that a shot because looking at your, code it looks fine.
I would recommend adding the didFailWithError method:
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
To your files as well because maybe your connection is failing for some reason as well.

Is your connection synchronous or async ?
If async, you shouldn't autorelease your ImageDownloader, because there are some chance that it would be released for the connectionDidFinishLoading message.
Try to alloc your ImageDownloader normally, then release it when it finishes the download (both in connectionDidFinishLoading and didFailWithError)

Related

NSURLConnection doesn't receive data when creating many downloading objects in iOS5

I have been searching for this problem on the SOF for several days and I still have not found the solution (say the same problem) yet.
I'm making and app that downloads 5 images simultaneously in an URL list (each image is on a different server).
I have an ImageDownloader class subclasses NSOperation and implements the NSURLConnectionDataDelegate.
So that I can add an instance of ImageDownloader to an operationQueue in the ViewController and it will run in a separate thread under the operationQueue. The line that add the downloader to the operationQueue is here:
downloader = [[ImageDownloader alloc] init];
[downloader downloadImageWithURL:[controller.URList objectForKey:[NSString stringWithFormat:#"%d",downloadIndex]] queue:queue andTag:downloadIndex + 100]; //my custom initialize
downloader.delegate = self;
[queue addOperation:downloader]; //use the addOperation method
Everything works fine in iOS6 but messed up in iOS5 (5.0 on my test device and 5.1 on my SDK), it just doesn't receive any response nor data by performing the methods didReceiveResponse and didReceiveData at all (these 2 methods are not jumped in).
After the timeout was exceeded, the runloop jumps into didFailWithError method and the program stalls.
As I understand, this means the runloop still runs right?
I tried to print out the error and all I got is: The request timed out.
When I reduce the number of downloading instances to 2 then it runs, but not with >=3 downloading instances.
One more information is that my network connection does limit the number of connection. But it work fine in iOS6, why it just doesn't work on iOS5?
I can still load the web in the simulator while the app is downloading.
So what kind of problem is this and how can I get over this problem?
Thanks in advance.
*Update:* as there are many classes and the problem's not been clearly detected yet, I will share here the whole project. You can download it directly from here:
DownloadingImage
As I just found out, if you're using credentials there is a chance that the server will reject them randomly every once in a while. So if you have a check to make sure previousFailureCount == 0 then you will most likely have a bug.
I've just figured out where my problem is, but not really understand why.
In my ImageDownloader class, I set up a runloop with done and currentRunLoop variables.
In the main method, I have a while loop for forcing the currentRunLoop run.
As I remove those "runLoop" stuffs, the app runs smoothly on both iOS6 and iOS5.
So change the entire ImageDownloader.m with these lines then it works (I commented out some useless (say harmful) lines):
//
// ImageLoader.m
// DownloadImagesTableView
//
// Created by Viet Ta Quoc on 6/25/13.
// Copyright (c) 2013 Viet Ta Quoc. All rights reserved.
//
#import "ImageDownloader.h"
#implementation ImageDownloader
#synthesize downloadData,delegate,queue,done,customTag;
NSRunLoop *currentRunLoop;
-(void)downloadImageWithURL:(NSString *)imageUrl queue:(NSOperationQueue*)opQueue andTag:(int)tag{
self.customTag= tag;
self.queue = opQueue;
// self.done = NO;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:imageUrl] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[connection start];
// currentRunLoop = [NSRunLoop currentRunLoop];
NSLog(#"Start downloading image %d...",customTag);
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(#"Received response...");
downloadData=[[NSMutableData alloc] initWithLength:0];
expectedDataLength=[response expectedContentLength];
NSLog(#"Image %d size: %lld kb",customTag,[response expectedContentLength]/1024);
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
float receivedLenght = [data length];
receivedDataLength=(receivedDataLength+receivedLenght);
float progress=(float)receivedDataLength/(float)expectedDataLength;
[delegate updateProgess:progress andIndex:[NSIndexPath indexPathForRow:customTag-100 inSection:0]];
[self.downloadData appendData:data];
// NSLog(#"Percentage of data received of tag %d: %f %%",self.customTag,progress*100);
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
[delegate finishedDownloadingImage:downloadData andTag:customTag];
// done = YES;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Warning" message:#"Network Connection Failed?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil, nil];
// NSLog(#"%#",[error debugDescription]);
NSLog(#"Connection failed! Error - %# %#",[error localizedDescription],[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
[alert show];
}
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
NSLog(#"Got here *(*&(**&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&");
}
-(void)main{
// do{
//// NSLog(#"Running....1");
// [currentRunLoop runUntilDate:[NSDate distantFuture]];
// // [currentRunLoop run];
// } while (!done);
// [currentRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
#end
Thank you guys for your supports.
==================================================================================
P/s: for anyone who interested in this problem, I update here my entire solution: DownloadImage_Final

NSURLConnectionDownloadDelegate method not getting called

i m working on a project that connect to server and download data from it. i like to support resume download if connection gets interrupt. my approach is to save the downloaded portion of data to a destination file; and if connection gets interrupted, i want to mark the downloaded portion using connection:didWriteData:totalBytesWritten:expectedTotalBytes and later resume from the stopped portion with server.
my code:
- (IBAction)connectToServer:(UIButton *)sender
{
// setup url and send request to server
NSURL *url = [NSURL URLWithString:BASED_URL];
self.urlRequest = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
self.urlConnection = [[NSURLConnection alloc] initWithRequest:self.urlRequest delegate:self];
// start receive data if connection established
if (self.urlConnection){
self.receivedData = [NSMutableData data];
NSLog(#"starting to receive data");
} else {
// handle error
NSLog(#"failed to connect to server");
}
}
- (void)doSomethingWithData
{
// handle data here
}
#pragma NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// received data
[self.receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// error connection
NSLog(#"connection failed");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Data receiving succeed, received: %d bytes of data", [self.receivedData length]);
}
- (void)connection:(NSURLConnection *)connection didWriteData:(long long)bytesWritten totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long)expectedTotalBytes
{
NSLog(#"not getting called");
}
my question is how come the "connection:didWriteData:totalBytesWritten:expectedTotalBytes" method never get called?
thanks so much!
chris
Have u added this in .h file:
#interface yourViewContoller : UIViewController <NSURLConnectionDataDelegate, NSURLConnectionDelegate>
According to Apple's documentation:
The NSURLConnectionDownloadDelegate protocol describes methods that should be implemented by the delegate of instances of NSURLConnection created using Newsstand Kit’s downloadWithDelegate: method.
Also, it says:
If you are using NSURLConnection directly, your delegate class should instead implement the methods defined in the NSURLConnectionDataDelegate protocol.

Multiple NSURLConnection & NSRunLoop

I am trying to speed up my application download speed. I used Asynchronous NSURLConnection to download contents from the server, it was working fine with one connection.
I use the code from this post to implement multiple delegate objects. Multiple NSURLConnection delegates in Objective-C
When I created 2 NSURLConnection objects, each one is trying to download different files.
The callback didReceiveData routine was called but the it only received data of the first NSURLConnection object until the first connection was done then it started to receive the data from the second NSURLConnection. I want these two connections to receive data at the same time,what should I do? Here is my current code.
-(IBAction) startDownloadClicked :(id) sender
{
while (bDownloading)
{
int nCurrentCon = 0;
while (nCurrentCon < 2)
{
[self downloadAFile:[filenameArray objectAtIndex:nCurrentCon]];
nCurrentCon++;
}
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
}
}
- (void) downloadAFile: (NSString*) filename
{
NSString* urlstr = #"ftp://myftpusername:password#hostname";
NSURLRequest* myreq = [NSURLRequest requestWithURL:[NSURL URLWithString:urlstr]];
DownloadDelegate* dd = [[DownloadDelegate alloc] init]; //create delegate object
MyURLConnection* myConnection = [[MyURLConnection alloc] initWithRequest:myreq delegate:dd
startImmediately:YES];
}
Then in my Delegate Object, I implemented these routines
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receiveBuffer setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"receiving data for %#", targetFileName); //the file name were set when this delegate object is initialized.
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Download Failed with Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"File %# - downloaded.", targetFileName);
}
Your code looks okay. I have a similar setup that works successfully (although there seems to be a limit of four concurrent conections).
The main difference between your and my code is that you use FTP while I use HTTP. Why don't you try it with HTTP connections just to see whether you have run into a restriction of FTP connections on the iPhone?

iPhone app crashes with no justifiable reason?

I am developing an app in which I have a table. In the table cell I have an imageview ( the images are displayed via url ) and a textview/webview. I start threads for each row to get the images in the
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
method ( if image is not already got ) and set the text of textview/webview from an array.
The problem arises when the images are being received and I pop the view, the application crashes giving the following message:
bool _WebTryThreadLock(bool), 0x1a0670: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
Now the situation becomes more weird if I don't release the textview/webview that I added to the cell, then every thing works fine.
Edit: the crash does not happens when I replace textview/webview with a label
Hoping I am clear in my question. If any thing is confusing please comment. I need to resolve this.
Thanks,
Nikhil
That's a huge mistake to use threads. Try to avoid using threads if you have other solutions !
In your case, just use an asynchronous NSURLConnection which will take care of downloading your image while not slowing your app ;)
Here is part of the code :
- (void) startDownload {
self.activeDownload = [NSMutableData data];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:#"blablabla"]] delegate:self];
self.imageConnection = conn;
[conn release];
}
#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.activeDownload appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR DOWNLOADING");
// Clear the activeDownload property to allow later attempts
self.activeDownload = nil;
// Release the connection now that it's finished
self.imageConnection = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"FINISH DOWNLOAD");
UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
self.activeDownload = nil;
self.imageConnection = nil;
//do whatever you want with your image
[image release];
}

UIWebView - stringByEvaluatingJavaScriptFromString - not changing text box value

Why doesn't this code work? It shows the Google screen but it doesn't change the text box value. I confirmed that the JS does work by running it in Safari, and this code seems to work otherwise since running alert('hi') does work.
NSURL *web_url = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *web_request = [NSURLRequest requestWithURL:web_url];
[web_screen loadRequest:web_request];
NSString *js_result = [web_screen stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test';"];
Just expanding on the previous answer. You need to conform to the UIWebViewDelegate protocol by setting the delegate property of the UIWebView like this:
web_screen.delegate = self;
Then you can implement one of the delegate methods to know when a request has finished loading and is therefore ready to have scripts run like so:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *js_result = [webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test';"];
}
For more information on the UIWebViewDelegate protocol visit the Apple site http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html
The Load URL action takes place asynchronously. It does not even start until your method has ended. So your javascript is being pushed into an empty UIWebView, then your method ends, then the load happens.
You need to let your method end before the js is pushed in. The standard approach for this is to use a Delegate object, which will have a method called on it when the load completes. Only then does it make sense to push in the javascript.
Does it work if you wait for the page to finish loading first?
Consider looking at NSURLConnection and its delegate methods. You can use these to check on the status of a download.
#interface
...
NSURLConnection *connectionInProgress;
NSData *googleRequestResponseData;
NSURL *googleURL;
...
#implementation
...
- (void) setUpRequest {
googleURL = [[NSURL URLWithString:#"http://www.google.com/"] retain];
googleRequestResponseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
#pragma mark NSURLConnection delegate methods
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[googleRequestResponseData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[web_screen loadData:googleRequestResponseData MIMEType:#"application/octet-stream" textEncodingName:#"utf-8" baseURL:googleURL];
NSString *js_result = [web_screen stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test';"];
NSLog (js_result);
[googleURL release];
[googleRequestResponseData release];
[connectionInProgress release];
connectionInProgress = nil;
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog (#"Connection failed to load data from Google!");
[googleURL release];
[googleRequestResponseData release];
[connectionInProgress release];
connectionInProgress = nil;
}
Alternatively, check out Ben Copsey's ASIHTTPRequest wrapper, which includes a simplified approach to asynchronous downloads (see ASINetworkQueue, specifically).
You can use ASINetworkQueue to run a method of your choice (to run the Javascript code, for example), once the request download is complete.
add '.innerHTML' after what you are searching for
In your case do the following
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *js_result = [webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test'.innerHTML"];
}
This worked for me .
check this for more info here