NSURL Loading data percentage Value - iphone

I need to read NSURL Loading data percentage value.
That is, I want to read how many percentage amount of data is loading on URL Loading time.
Suppose a URL take 30 seconds to loading data completely, I want to know in 15th sec how many percentage of data is loading in my String, and 20th sec how many percentage of data is loading in my String, like this I need.

First of all, you will have to use NSURLConnection. In its delegate's implementation include the following method:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
long long contentLength = [response expectedContentLength];
...
}
Note that the only way to know how many bytes the server is going to return is to retrieve the value from its HTTP response. If you find that expectedContentLength returns -1 (and you should be prepared for that), the server does not return a meaningful value for the downloaded content size, perhaps because it doesn't support the feature. In such a case you should resort to alternative ways to get the byte size.

Related

Showing Accurate Progress In UIProgressView While Downloading Images in iphone

I have four urls which consists images...
I'm downloding those images and placing them into documents folder..
here is my code..
-(void)viewDidLoad
{
NSMutableArray *myUrlsArray=[[NSMutableArray alloc]init];
[myUrlsArray addObject:#"http://blogs.sfweekly.com/thesnitch/steve_jobs3.jpg"];
[myUrlsArray addObject:#"http://www.droid-life.com/wp-content/uploads/2012/12/Steve-Jobs-Apple.jpg"];
[myUrlsArray addObject:#"http://2.bp.blogspot.com/-T6nbl0rQoME/To0X5FccuCI/AAAAAAAAEZQ/ipUU7JfEzTs/s1600/steve-jobs-in-time-magazine-front-cover.png"];
[myUrlsArray addObject:#"http://images.businessweek.com/ss/08/09/0929_most_influential/image/steve_jobs.jpg"];
[myUrlsArray addObject:#"http://cdn.ndtv.com/tech/gadget/image/steve-jobs-face.jpg"];
for (int i=0; i<myUrlsArray.count; i++)
{
[self downloadImageFromURL:[myUrlsArray objectAtIndex:i] withName:[NSString stringWithFormat:#"MyImage%i.jpeg",i]];
}
}
#pragma mark- downloading File
-(void)downloadImageFromURL:(NSString *)myURLString withName:(NSString *)fileName
{
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:myURLString]]];
NSLog(#"%f,%f",image.size.width,image.size.height);
// Let's save the file into Document folder.**
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
NSString *jpegPath = [NSString stringWithFormat:#"%#/%#",documentsPath,fileName];// this path if you want save reference path in sqlite
NSData *data2 = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];//1.0f = 100% quality
[data2 writeToFile:jpegPath atomically:YES];
}
NOW... I need to display a UIProgressView for above downloading progress accurately.
how can i achieve this functionality...
Can any one provide some guidelines to achieve this..
Thanks in advance...
I'd suggest you use some asynchronous downloading technique (either AFNetworking, SDWebImage, or roll your own with delegate-based NSURLSession) rather than dataWithContentsOfURL so that (a) you don't block the main queue; and (b) you can get progress updates as the downloads proceed.
I'd also suggest creating a NSProgress for each download. When your delegate method gets updates about how many bytes have been downloaded, update the NSProgress object.
You then can associate each NSProgress with a observedProgress for a UIProgressView, and when you update your NSProgress, the UI can be updated automatically.
Or, if you and a single UIProgressView to show the aggregate progress of all of the NSProgress for each download, you can create a parent NSProgress, establish each download's NSProgress as a child of the parent NSProgress, and then, as each download updates its respective NSProgress, this will automatically trigger the calculation of the parent NSProgress. And again, you can tie that parent NSProgress to a master UIProgressView, and you'll automatically update the UI with the total progress, just by having each download update its individual NSProgress.
There is a trick, though, insofar as some web services will not inform you of the number of bytes to be expected. They'll report an "expected number of bytes" of NSURLResponseUnknownLength, i.e. -1! (There are logical reasons why it does that which are probably beyond the scope of this question.) That obviously makes it hard to calculate what percentage has been downloaded.
In that case, there are a few approaches:
You can throw up your hands and just use an indeterminate progress indicator;
You can try changing the request such that web service will report meaningful "expected number of bytes" values (e.g. https://stackoverflow.com/a/22352294/1271826); or
You can use an "estimated download size" to estimate the percentage completion. For example, if you know your images are, on average, 100kb each, you can do something like the following to update the NSProgress associated with a particular download:
if (totalBytesExpectedToWrite >= totalBytesWritten) {
self.progress.totalUnitCount = totalBytesExpectedToWrite;
} else {
if (totalBytesWritten <= 0) {
self.progress.totalUnitCount = kDefaultImageSize;
} else {
double written = (double)totalBytesWritten;
double percent = tanh(written / (double)kDefaultImageSize);
self.progress.totalUnitCount = written / percent;
}
}
self.progress.completedUnitCount = totalBytesWritten;
This is a bit of sleight of hand that uses the tanh function to return a "percent complete" value that smoothly and asymptotically approaches 100%, using the kDefaultImageSize as the basis for the estimation.
It's not perfect, but it yields a pretty decent proxy for percent completion.
Your call to dataWithContentsOfURL is synchronous, meaning you don't get updates as the download is in process.
You can use a library like AFNetworking (https://github.com/AFNetworking/AFNetworking) which has callbacks to the progress of the download.
Actually a better solution is to use SDWebImage manager which will load the images in the background for you and cache them. Then the next time you use that image it will check the cache. Google it.
That way the user also doesn't have to sit around and wait while you're downloading stuff..
Then look at this other question that has some ideas on how to do a status:
How to show an activity indicator in SDWebImage
Do not use dataWithContentsOfURL, you are blocking the main thread until the data arrives.
Instead create your own connection with NSURLConnection and start listening to your delegate.
connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response: get the total data size with [response expectedContentLength].
connection:(NSURLConnection *)connection didReceiveData:(NSData *)data: This is where you do your calculations and update your UIProgressView. Something like, loadedBytes/total data size.
Good luck.

RedPark Cable readBytesAvailable read twice every time

I have not been able to find this information anywhere. How long can a string be send with the TTL version of the redpark cable?
The following delegate method is called twice when I print something thorough serial from my Arduino, an example of a string is this: 144;480,42;532,40;20e
- (void) readBytesAvailable:(UInt32)length{
When I use the new function methods of retrieving available data [getStringFromBytesAvailable] I will only get 144;480,42;532,40; and then the whole function is called again and the string now contains the rest of the string: 20e
The following method is working for appending the two strings, but only if the rate of data transmission is 'slow' (1 time a second, I would prefer minimum 10 times a second).
-
(void) readBytesAvailable:(UInt32)length{
if(string && [string rangeOfString:#"e"].location == NSNotFound){
string = [string stringByAppendingString:[rscMgr getStringFromBytesAvailable]];
NSLog(string);
finishedReading = YES;
}
else{
string = [rscMgr getStringFromBytesAvailable];
}
if (finishedReading == YES)
{
//do stuff
}
finishedReading = NO;
string = nil;
}
}
But can you tell my why the methods is called twice if I write a "long" string, and how to avoid this issue?
Since your program fragment runs faster then the time it takes to send a string, you need to capture the bytes and append them to a string.
If the serial data is terminated with a carriage return you can test for it to know when you have received the entire string.
Then you can allow your Arduino to send 10 times a second.
That is just how serial ports work. You can't and don't need to avoid those issues. There is no attempt at any level of the SW/HW to keep your serial data stream intact, so making any assumptions about that in your code is just wrong. Serial data is just a stream of bytes, with no concept of packetization. So you have to deal with the fact that you might have to read partial data and read the rest later.
The serialPortConfig within the redparkSerial header file provided by RedPark does, in fact, give you more configuration control than you may realize. The readBytesAvailable:length method is abstracted, and is only called when one of two conditions is met: rxForwardingTimeout value is exceeded with data in the primary buffer (default set to 100 ms) or rxForwardCount is reached (default set to 16 characters).
So, in your case it looks like you've still got data in your buffer after your initial read, which means that the readBytesAvailable:length method will be called again (from the main run loop) to retrieve the remaining data. I would propose playing around with the rxForwardingTimeout and rxForwardCount until it performs as you'd expect.
As already mentioned, though, I'd recommend adding a flag (doesn't have to be carriage return) to at least the end of your packet, for identification.
Also, some good advice here: How do you design a serial command protocol for an embedded system?
Good luck!

How to Check if an image is valid on iPhone

How to Check if an image is valid
For example, when I cached an image which was downloaded only half and failed, and this image is invalid, then I want to know it's an invalid image and download again.
(When I use the broken image, Xcode console logs an error:
ImageIO: PNG IDAT: CRC error )
So I want find a mechanism to check image's validation
for different kinds of JPEG,PNG,etc
anybody has some clues?
I would start by checking for valid header.
Secondly the footer. Usually the last 8 bytes uint values in order are
'73,69,78,68,174,66,96,130'.
This converted into a Int64 equals 5279712195050102914
This should do for a png :)
if (memcmp(img_bytes, "\211PNG", 4) != 0||OSReadBigInt64(img_bytes,(length - 8))!=5279712195050102914)
{
//Bad Data! Free your data and return or something
}
It happens because you are using same class to download image file from server and you request consequent download of same file, while it is already downloading that file, which fails the earlier one file download and results in partly downloaded file.
I suggest you to get the file size of the image & compare with the image file just downloaded.
For loading images from the network there are two obvious failure cases:
The downloaded file was not an image at all.
The downloaded data only contains part of the image data.
For the first case nil checking the return value of various UIImage methods is probably the best way to handle this error case.
The following class methods on UIImage will return nil if the image could not be initialized with the data it was provided: + (UIImage *)imageWithData:(NSData *)data and + (UIImage *)imageWithContentsOfFile:(NSString *)path.
Code that does the nil check might look like this:
UIImage *image = [UIImage imageWithContentsOfFile:pathToImage];
if (image) {
// The image was loaded. Display it
}
else {
// The image was not loaded. Redownload or display a placeholder, etc...
}
For the second failure case it is likely the result of lost connection. For this case the failure is best handled in the NSURLConnection's delegate. When downloading the image if - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error is called then the data for the request should be discarded.
Also keep in mind that didFailWithError: will not be called for 4xx or 5xx responses from the server. It is called when the connection is cut off for other reasons. It would generally be a good idea to make sure you only write image data to disk when the server has responded with a 200 OK.

NSURLConnection and Content-Encoding

I have an NSURLConnection which is downloading a web page. I get the Content-Length which is much smaller than the actual size of the file.
I noticed that the header also says:
Content-Encoding:gzip
I guess the size returned by Content-Length is the compressed size, however the NSData returned by NSURLConnection has been decompressed.
Firstly does NSURLConnection automatically decompress it?
And how do I get the length of either the uncompressed file (instead of Content-Length)
If you need a progress bar, why not try ASIHTTPRequest? It has a number of built in features that help manage a progress bar.
If what you're trying to do is make some sort of progress bar or progress indicator for an NSURLConnection download, try the below code. It works like a charm in a few of my apps.
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// append the new data to receivedData (a global variable).
[receivedData appendData:data];
// calculate number of kilobytes
int kb = [receivedData length] / 1024;
// update a label, or some other visula thingy
self.downloadProgressLabel.text = [NSString stringWithFormat:#"Downloaded\n%d kB", kb];
}

how to make asynchronous call using NSThread

i have made one list of images + respective data in tableview.
it takes long time while loading
i want to make multithreading two methods
1> parsing of data
2> parsing of images
i want to execute parsing of data first after that i can select any of rows listed even though images not been loaded(/parsed) because the images is parsed after the parsing of data and it takes long time.
from where should i call these both the methods.
and how enable the selection on row after parsing of the data...
how to do multithread both the methods
waiting for your great responce
Thanking in advance
You likely don't want to use NSThreads - at least not directly.
What you do is subclass NSOperation.
There are a few ways to do what you have in mind. If you know the total number of rows in your table right from the start, then things are simpler:
Make a subclass of NSOperation called MyParseDataOperation. Then make one MyParseDataOperation for each row in your table. When the operation is done, you need to message your main thread with the resulting data.
Code below is full of errors, incomplete. etc.
ie in your MyParseDataOperation class:
MyParseDataOperation
-(id)initWithStuff:(NSURL*)stuff forTableRow:(int)row;
{
blah blah -
// here is where I make sure I have all the data I need for main() which is called in the background on some random thread at some future time.
}
-(void)main;
{
// use data like Urls, file names, etc passed in to the initWithStuff method
get stuff
parse stuff
// ok now you have the data
NSMutableDictionary* parsedData = [NSMutableDictionary dictionary];
[parsedData setObject:[NSNumber numberWithInt:row] forKey:#"row"];
[parsedData setObject:stuff i figured out forKey:#parsed];
[tableDataSource performSelectorOnMainThread:#selector(dataParsed) withObject:parsedData];
}