calculating total time of downloading data? - iphone

i am using apple's sample URLCache,but when i mention url, it loads data perfectly
but i want to calculate time of downloading(till completion),is there anyh built in method?

Add NSDate property to your class, name it,let's say, downloadStart and when download starts, save actual time to it - self.downloadStart = [NSDate date];
Then in -connectionDidFinishLoading: delegate method implementation do:
NSDate *downloadEnd = [NSDate date];
NSTimeInterval totalTime = ([downloadEnd timeIntervalSince1970] - [downloadStart timeIntervalSince1970]);
//Total time now contains number of seconds since download start time
NSLog(#"Download finished in %f seconds", totalTime);
self.downloadStart = nil;
That's it. Please note that the code above is just a kind of abstract how to do the trick, so don't use in copy & paste manner.

Related

how to keep running NSTimer when app goes in background

I am creating puzzle game application and in that I am displaying time (i.e 01:20) using NSTimer. NSTimer is paused when application gone in background but i want to continue it even application is in background state.
for example timer count is 15 sec when app gone in background and I put it for 5 sec and become in foreground now I need to timer count changes to 20 sec
I have searched a lot but didn't get good answer.
So Please suggest me how can I achieve this.
Don't think of a timer as an object for timing something. Think of it rather as an object that pulses at a given frequency. To measure time, record a start time and compare it to the current time.
To record the start time, write it to a file as follows, probably in appWillResignActive:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = [path stringByAppendingPathComponent:#"saveme.dat"];
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self.startDate];
[data writeToFile:filename atomically:NO];
// invalidate timer
When appWillBecomeActive:
NSData *data = [NSData dataWithContentsOfFile:filename]; // using the same code as before
self.startDate = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// start a timer for the purpose of pulsing only
Elapsed time at this point is:
NSDate *now = [NSDate date];
NSTimeInterval = [now timeIntervalSinceDate:self.startDate];
All of the foregoing can be done without running in the background. If you really need a timer to fire in the background, see this apple ref. Under "Background Execution". In a nutshell, you can do it, but Apple will make you meet several criteria before approving the app -- like it must be finite and provide utility for the user.
Create a NSDate ivar in your class to manage the starting time.
#implementation SomeClass {
NSDate *startTime;
}
For your timer, simply calculate the time through math on this date. Your timer is more used to invoke the method that does this calculation rather than determine the time itself...
[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
Logic for your method...
- (void)updateTimer {
if (!startTime) {
startTime = [NSDate date];
}
NSInteger secondsSinceStart = -(NSInteger)[startTime timeIntervalSinceNow];
NSLog(#"%d", secondsSinceStart);
}
You're going to need to write that information out to a file or cache the time at exit. Then when the application resumes you read that value in, do some math, and restart your timer.
In your AppDelegate as the app is going to background save the time to a file or NSUserDefaults. You can call NSDate's class method to get an Integer value you can easily store.
+ (NSTimeInterval)timeIntervalSinceReferenceDate
At application resume, read in the value. Get the current timeIntervalSinceReferenceDate and subtract. You should have the number of seconds that have elapsed.
I would recommend saving the start time as an NSDate object, and then having an NSTimer that, every second while the app is running, updates the displayed time by calculating the time interval between the current time and the start time. Pause the timer when your app goes into the background (so that you don't get a lot of unnecessary fires when your app starts back up) and restart it whenever the app enters the foreground.
If you want the data to be preserved across the app shutting completely (by being left in the background for too long, or closed in the app switcher) then you'll need to save data to disk at appropriate times.
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5f
target:self
selector:#selector(showTime)
userInfo:NULL
repeats:YES];
- (void)showTime
{
NSDate *now=[NSDate date];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"HH:mm:ss"];
timeLabel.text=[dateFormatter stringFromDate:now];
}
Hope this answer will help you....

Adding Timer to iPhone

I am trying add a feature where On certain push, my timer will be started and even the app is close the timer will continue. Lets say my Points were 10 and now timer started. Once i close the app, maybe next time if i open the app the
1- If before 20 min it will show a count down timer running
2- if after 20 min at app again start it will add point to 10.
Now what Kind of timer or class can help me do this?
Regards
NSTimer will not continue more than 600 seconds even if your app is in background, rest terminating the app.
you can rather do this:
NSString *prevTimestamp = [NSString stringWithFormat:#"%d",
[[NSDate date] timeIntervalSince1970]];
store this prevTimestamp in NSUserDefaults, and when coming back to the app,
NSString *nowTimestamp = [NSString stringWithFormat:#"%d",
[[NSDate date] timeIntervalSince1970]];
time difference will be [nowTimestamp floatValue] - [prevTimestamp floatValue]
In your delegate for app terminiation save the time in NSUserdefaults and while you laucnch the app read it back and go on to add the time on that.
Within your applicationdelegate, you have these functions:
-(void)applicationDidEnterBackground:(UIApplication *)application;
and
-(void)applicationWillEnterForeground:(UIApplication *)application;
From these functions you can track time through something like this:
-(void)applicationDidEnterBackground:(UIApplication *)application
{
backgroundTime = [[NSDate date] timeIntervalSince1970];
}
-(void)applicationWillEnterForeground:(UIApplication *)application
{
double timetoAppend = [[NSDate Date] timeIntervalSince1970] - backgroundTime];
// from here you need to add the timetoAppend to your own variable
}

How to get an NSDate from an integer passed in as and id?

This is driving me nuts so I hope someone can help an Objective-C noob figure this out. Here's the deal:
I'm developing an iPhone app using Titanium Appcelerator and I'm trying to create an add-on module in XCode that will allow me to send an event to the iPhone calendar. What I'd like to do is to calculate the date and time in terms of seconds since Jan 1, 2001 (GMT) and send it directly to calendar without having to mess with the string-to-date stuff that seems always to return the wrong time. To this point, I've not been able to get the integer into the event date fields, both of which are NSDate types.
Titanium takes arguments from Javascript and compiles it into object code, so I can call my "cal" object like this:
var startDate = 316367923;
var endDate = 316367923;
var results = cal.newEvent(startTime,endTime)
. . . and this is how the "cal" object receives that call:
-(BOOL)newEvent:(id)args {
id startDate = [args objectAtIndex:0];
id endDate = [args objectAtIndex:1];
...
What I'm hoping to do get these integers into the event object:
EKEventStore *eventDB = [[EKEventStore alloc] init];
EKEvent *theEvent = [EKEvent eventWithEventStore:eventDB];
...
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) startDate];
theEvent.endDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) endDate];
This compiles with no errors but causes my app to bomb nonetheless, so I'm figuring I've got something missing in my understanding. Any idea of where I'm going wrong?
Thanks,
Mark
Quite probably 'args' is an NSArray, hence startDate and endDate are objects, not literals. You probably want to do something like:
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:[startDate intValue]];
If e.g. startDate is an NSNumber. Otherwise, check out the Titanium docs to find out the type of numbers passed in.
This may not be the cause of your crash, but the initWithTimeIntervalSinceReferenceDate NSDate method is expecting an NSTimeInterval (defined as typedef double NSTimeInterval) not an integer.
i.e.: Its method signature is:
- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds
I'd bet startDate and endDate are being converted to NSNumber objects instead of ints. Therefore, try the following lines:
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) [startDate intValue]];
theEvent.endDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) [endDate intValue]];
I doubt that your crash has anything to do with it but, you might be leaking. The lines:
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) startDate];
theEvent.endDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) endDate];
assign an object with retain count 1, if the setter for startDate and EndDate takes ownership of them (I don't know if java will do that or not so I might be wrong) you must store them in a local variable before assigning them to theEvent, so that you can call release afterwards.
so it would look like this:
NSDate *sDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:[startDate intValue]];
theEvent.startDate = sDate;
[sDate release];

timeIntervalSinceNow returning random numbers

timeInterval keeps returning random numbers. I would think the interval would continue to increase with each call but sometimes I get negative numbers and sometimes positive numbers.
NSDate *date = groceryItem.lastPurchased;
double timeInterval = [date timeIntervalSinceNow];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d", timeInterval];
%d is for integers, use %f for double
[NSString stringWithFormat:#"%f", timeInterval];
Try this instead:
NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:groceryItem.lastPurchased];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%f", timeInterval];
A few points on this snippet:
I've used NSTimeInterval instead of double in the second line. They are equivalent because it's just a typedef but it makes for clearer code.
Rather than getting the time interval from a date in the past, I'm calculating the date and time right now with [NSDate date] and getting the time interval from groceryItem.lastPurchased. This will return a postive number as long as groceryItem.lastPurchased is in the past.
I've edited my original code to pass groceryItem.lastPurchased to the time interval calculation directly. It isn't always a good idea to declare a variable for an item that is going to be used only once, especially in non-garbage-collected environments. Although declaring variables might make the code more readable there are other ways of improving readability. For example, in this case change the property to groceryItem.lastPurchasedDate which makes it a lot clearer.
If the receiver is earlier than the current date and time, the return value is negative. so if date is before now it will be negative.
timeIntervalSinceNow will return the interval between the receiver and the current date and time. If the receiver is earlier than the current date and time, the return value is negative. If the receiver is later than the current date and time, the return value is positive.
Hope this helps.
This code [NSString stringWithFormat:#"%d", timeInterval]; is wrong. It is a DOUBLE. don't use %d. Use %f instead.
[NSString stringWithFormat:#"%f", timeInterval];
It has been answered correctly above, I'd also add you should use the NSTimeInterval type rather than double as well.
You should use a negative sign as below
double timeInterval = - [date timeIntervalSinceNow];

Displaying timecode using NSTimer and NSDateFormatter

I am very close to completing my first iphone app and it has been a joy. I am trying to add running timecode using the current time via an NSTimer displaying the current time (NSDate) on a UILabel. NSDate is working fine for me, showing hour, minute, second, milliseconds. But instead of milliseconds, I need to show 24 frames per second.
The problem is that I need the frames per second to be synced 100% with the hour, minute and second, so I can't add the frames in a separate timer. I tried that and had it working but the frame timer was not running in sync with the date timer.
Can anyone help me out with this? Is there a way to customize NSDateFormatter so that I can have a date timer formatted with 24 frames per second? Right now I'm limited to formatting just hours, minutes, seconds, and milliseconds.
Here's the code I'm using right now
-(void)runTimer {
// This starts the timer which fires the displayCount method every 0.01 seconds
runTimer = [NSTimer scheduledTimerWithTimeInterval: .01
target: self
selector: #selector(displayCount)
userInfo: nil
repeats: YES];
}
//This formats the timer using the current date and sets text on UILabels
- (void)displayCount; {
NSDateFormatter *formatter =
[[[NSDateFormatter alloc] init] autorelease];
NSDate *date = [NSDate date];
// This will produce a time that looks like "12:15:07:75" using 4 separate labels
// I could also have this on just one label but for now they are separated
// This sets the Hour Label and formats it in hours
[formatter setDateFormat:#"HH"];
[timecodeHourLabel setText:[formatter stringFromDate:date]];
// This sets the Minute Label and formats it in minutes
[formatter setDateFormat:#"mm"];
[timecodeMinuteLabel setText:[formatter stringFromDate:date]];
// This sets the Second Label and formats it in seconds
[formatter setDateFormat:#"ss"];
[timecodeSecondLabel setText:[formatter stringFromDate:date]];
//This sets the Frame Label and formats it in milliseconds
//I need this to be 24 frames per second
[formatter setDateFormat:#"SS"];
[timecodeFrameLabel setText:[formatter stringFromDate:date]];
}
I would suggest that you extract the milliseconds from your NSDate - this is in seconds, so the fraction will give you milliseconds.
Then just use a plain format string to append the value using NSString method stringWithFormat:.
Lots-a-overhead with NSFormatter + NSDate. Plus it seems to me that NSDate doesn't provide a "simple" microtime situation for simple stuff.
Mogga provided a nice pointer, here's a C / Objective-C variant:
- (NSString *) formatTimeStamp:(float)seconds {
int sec = floor(fmodf(seconds, 60.0f));
return [NSString stringWithFormat:#"%02d:%02d.%02d.%03d",
(int)floor(seconds/60/60), // hours
(int)floor(seconds/60), // minutes
(int)sec, // seconds
(int)floor((seconds - sec) * 1000) // milliseconds
];
}
// NOTE: %02d is C style formatting where:
// % - the usual suspect
// 02 - target length (pad single digits for padding)
// d - the usual suspect
See this discussion for more info on this formatting.
Here's a Processing/Java equivalent that's fairly straightforward to repurpose.
String timecodeString(int fps) {
float ms = millis();
return String.format("%02d:%02d:%02d+%02d", floor(ms/1000/60/60), // H
floor(ms/1000/60), // M
floor(ms/1000%60), // S
floor(ms/1000*fps%fps)); // F
}