"Streaming" data: Keep parser open or continually create a new one? - iphone

I wanted to know what is more efficient for what I am doing:
I'm bringing in (very small - 4kb or less each) .xml files which contain GPS coordinates of a vehicle. I am then parsing them (very light parsing involved) and sending them back to the delegate.
Currently, I am using a a timer which every 1 second calls the following:
-(void)refreshGPSData:(NSTimer *)theTimer{
GPSParser *parser = [[GPSParser alloc] initWithName:#"route"];
[parser parseRssFeed:#"http://thefeed.com/feed.xml" withDelegate:self];
[parser release];
}
My question is, would it be more efficient to do this in a different way that isn't continuously alloc and initing the parser? Should I alloc+init only one parser and then call "parseRssFeed" every 1 second. Or should i not use a timer, but instead call "parseRssFeed" every time the parser finishes and returns data to the delegate? What is best programming practice?
Please let me know if i have provided enough information.
Thank you!

This depends how often you want to use the parser. If you only parse data once a minute there is no need to store a parser in an object.
If you parse the data 10 times a second you have to allocate once and store the parser.
As the other poster (who deleted his answer because this is not a .net question) suggested I made a little performance test to show that an alloc is a really slow operation.
for (NSTimeInterval i = 0; i < 1000; i++) {
self.label1.text = [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:i]];
}
vs
for (NSTimeInterval i = 0; i < 1000; i++) {
NSDateFormatter *localDateFormatter = [[NSDateFormatter alloc] init];
self.label2.text = [localDateFormatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:i]];
[localDateFormatter release];
}
gave a result of 0.0017 seconds for the first version, and 0.28 seconds for the second version. You'll get the idea. Yes, NSDateFormatter might be one of the more complex examples of an object.
If you want to use an object like a parser or a dateformatter often I would store it somewhere.

Related

Nslog timestamp

I want to nslog the device motion timestamp property .
The device motion is in the class CMMotionManager.devicemotion.timestamp
Any ideas.
Here the solution I put in place because the date is according to Apple documentation :
The time stamp is the amount of time in seconds since the phone booted.
I first save the originDate at the first mesure (if my NSDate is nil).
[self.motionManager startGyroUpdatesToQueue:self.queue withHandler:^(CMGyroData *gyroData, NSError *error) {
if (self.originDate == nil) {
self.originDate = [NSDate dateWithTimeIntervalSinceNow:-gyroData.timestamp];
}
}];
Then I can display when I want the real date like this :
[NSDate dateWithTimeInterval:mygyroData.timestamp sinceDate:self.originDate]
Don't forget to reset the originDate to nil if you need to restart some mesure.
Edit: Please see Nicolas Lauquin's answer. Per the comments, the following solution is not correct but is retained here for history (and because I can't delete it since it is currently marked accepted).
The timestamp property is an NSTimeInterval, so you should be able to do:
NSLog(#"Motion at time: %#",
[NSDate dateWithTimeIntervalSinceReferenceDate:devicemotion.timestamp]);
NSTimeInterval is just a typedef'd double type, so you could use %f instead of %# and log it directly.
Also, the docs don't indicate whether this timestamp is set against Apple's reference date or the standard *nix date, so you may need to use [NSDate dateWithTimeIntervalSince1970:] if the aforementioned method returns dates far in the future.
As #davidbitton has suggested the CMDeviceMotion's timestamp is relative to the last device boot, the correct NSDate could be derived by
NSDate *startupTime = [NSDate dateWithTimeIntervalSinceNow:
-1 * [[NSProcessInfo processInfo] systemUptime]];
NSDate *deviceMotionDate = [NSDate dateWithTimeInterval:devicemotion.timestamp
sinceDate:startupTime];
This should yield a roughly accurate NSDate object, assuming #davidbitton is correct. (reference: NSProcessInfo -systemUptime)
However, given how complicated this is, I would now suggest for simplicity that, given the nature of the timestamp property, that you log it in a format string as something like
"... event logged at %0.2f seconds since startup...", devicemotion.timestamp

Trying to save long long into NSNumber from String

I am trying to save a long long number (received as a string) such as '80182916772147201' into an NSNumber.
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterBehaviorDefault];
[item setObject:[f numberFromString:#"80182916772147201"] forKey:#"theID"];
[f release];
When I NSLog this out, assuming the string was '80182916772147201' I get:
NSLog(#"%lld", [[item objectForKey:#"theID"] longLongValue]);
Returns: '80182916772147200' - Note the rounded down final digit.
What am I doing wrong?
The problem is that NSNumberFormatter has decided to represent that number as a floating-point number. To force it to use integers only:
[f setAllowsFloats:NO];
Can you try this?
NSString *numStr = [NSString stringWithFormat:#"%llu", [myNum unsignedLongLongValue]];
This makes a few reasonable assumptions such as numStr will only contain numeric digits and it contains a 'valid' unsigned long long value. A drawback to this approach is that UTF8String creates what essentially amounts to [[numStr dataUsingEncoding:NSUTF8StringEncoding] bytes], or in other words something along the lines of 32 bytes of autoreleased memory per call. For the vast majority of uses, this is no problem what-so-ever.
For an example of how to add something like unsignedLongLongValue to NSString that is both very fast and uses no autoreleased memory as a side effect, take a look at the end of my (long) answer to this SO question. Specifically the example implementation of rklIntValue, which would require only trivial modifications to implement unsignedLongLongValue.

Objective-C Library for Sunrise and Sunset?

Is there an Objective-C (or C) library (that is compatible with core location) that can tell me the time of sunrise and sunset for any given calendar day?
EDSunriseSet is an open source and free Objective-C wrapper for the C languages routines created by Paul Schlyter.
Calculation is done entirely by the C-code routines. EDSunrisetSet bridges those calculations to common Cocoa classes (NSDate, NSTimeZone, ...)
I've actually ported the KosherJava Library and plan to make it available soon on GitHub!
Edit:
KosherCocoa is now live on GitHub! If you don't need the hebrew calendar related code, you can delete the "calendar" file. The class files are separated nicely into folders based on the kinds of calculations that they do.
Edit: KosherCocoa us due to be replaced with a modern and more complete update as soon as I can. The above link now points at a legacy repo.
I have used a library called SUNWAIT. Very simple, effective - easy to use!
Try this: https://github.com/mourner/suncalc/
Very clear and easy to implement, although it writen by javascript but it is easy to convert it to
objective-C
It also support for calculate sun, moon position and coordinate.
After not finding a simple Swift alternative, I created Solar: a Swift built micro-library for Sunrise / Sunset.
Just a note.. if you use the Berkley one... well it doesn't work (in Australia as least).
It does include the Paul Schlyter C code though, which is great.
If you want it to work anywhere, best to just calc the dates in UTC.
In SunriseAndSunset.m, replace the code from
double rise;
double set;
as follows:
sun_rise_set(theYear, theMonth, theDay, lon, lat, &rise, &set);
int hours = HOURS(rise);
int mins = MINUTES(rise);
int sethrs = HOURS(set);
int setmins = MINUTES(set);
NSTimeInterval riseOffset = ((hours * 60) + mins) * 60;
NSTimeInterval setOffset = ((sethrs * 60) + setmins) * 60;
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ssZ"];
NSString *dateStr = [NSString stringWithFormat:#"%i-%02d-%02dT00:00:00+0000", theYear, theMonth, theDay];
NSDate *utcMidnight = [formatter dateFromString:dateStr];
NSDate *utcSunrise = [utcMidnight dateByAddingTimeInterval:riseOffset];
NSDate *utcSunset = [utcMidnight dateByAddingTimeInterval:setOffset];
[formatter release];
[gregorian release];
return [NSDictionary dictionaryWithObjectsAndKeys:utcSunrise, #"sunrise", utcSunset, #"sunset", nil];
try this one: https://github.com/berkley/ObjectiveCUtil

What is the fastest routine to convert NSArrays to C-style (double) arrays?

I have 2 NSArray (Mutable, actually) that I am trying to convert to a C-style double array for a c routine i am passing them to.
Here is my Objective-C routine:
NSMutableDictionary *childDictionary = [myParentDictionary objectForKey:resort_code];
latitudeArray = [childDictionary objectForKey:#"lat"];
longitudeArray = [childDictionary objectForKey:#"lon"];
int nvert = [latitudeArray count];
double laArray[nvert];
double loArray[nvert];
for(int i=0; i<nvert; i++) {
double dLat = [[latitudeArray objectAtIndex:i]doubleValue];
double dLon = [[longitudeArray objectAtIndex:i]doubleValue];
laArray[i] = dLat;
loArray[i] = dLon;
}
This takes upwards of 3-8 seconds on the 3G iPhone (instantaneous on the simulator -- yet another reason to test on the device )
is there faster way? I have to end up with laArray[i] and loArray[i] as c-style arrays of doubles.
(to expand on the question for the benefit of a commenter):
Each array consists of #"38.448745" (lat) and #"-122.9847684" (lon) style content. I do this cos to be pushed onto an NSArray, the lat and lon need to be objects. I simply used:
[latitudeArray addObject:[NSString stringWithFormat: #"%.10f",dlat]];
[longitudeArray addObject:[NSString stringWithFormat: #"%.10f",dlon]];
I suppose I could change that to:
[latitudeArray addObject:[NSNumber numberWithDouble: #"%.10f",dlat]];
[longitudeArray addObject:[NSNumber numberWithDouble: #"%.10f",dlon]];
...which may reduce the conversion time of
double dLat = [[latitudeArray objectAtIndex:i]doubleValue];
but wouldn't I still need that exact line to convert from NSString to double? It just may work faster?
thx
dlat is a double, right?
So instead of:
[latitudeArray addObject:[NSString stringWithFormat: #"%.10f",dlat]];
Do:
[latitudeArray addObject:[NSNumber numberWithDouble:dlat]];
They both respond to doubleValue but the NSNumber should not have to do any string parsing since it's stored as a numeric value already. And you never have to go to a string at all.
I suspect you have an array of strings like #"213.12385" that need to be parsed and converted when you call doubleValue on them. If that is where the issue is, the C arrays have nothing to with this.
Only thing I would add here is to throw Shark on this and see where it's spending it's time. If it's spending time in doubleValue find a different way to parse the strings with preprocessing in background or something. If it's in objectAtIndex: perhaps fast enumeration would help. If it's somewhere else entirely then you know it's not this snippet that's slow.
For the general case of converting an NSArray to a C array, you can use getObjects:. In this case, though, want you actually want is not to convert the NSArray, but to derive an array of doubles from an NSArray of some unspecified object type.
One obvious way to speed things up would be fast enumeration rather than sending a message to get the object for each iteration of the loop. I suspect the real solution, though, is outside your algorithm. The slowness probably comes from transforming whatever objects the array contains into doubles, in which case you'll need to find a way around that — maybe store doubles all along, maybe do the conversion in the background, etc. If you're creating the arrays yourself and there isn't some compelling reason for the objects to be strings, you should use NSNumbers instead. Those should be quite a bit faster.
The best solution is probably to make sure those values never end up in an NSArray as NSString values. I would attack this at the source.
So you edited your question and added that you are actually building those arrays. So why not use native arrays of doubles or floats from the start? I usually recommend against this but in your case it sounds like there is a huge performance gain.
Possibly using fast iteration, but I doubt that will really speed up your loop.

Memory Leaks - Formatting a String To Display Time, Each Second

Hey guys. I have a method that gets called each second which I want to use to display the time that my app has been doing it's work. Currently the class I'm using (Which I did not create) has a property named progress which stores the total number of seconds.
I have already written some code which takes these seconds and formats it into a readable string. I'm new to this, so pardon me if it's not the best code. I welcome any suggestions:
// hours, minutes, and seconds are instance variables defined as integers
int totalSeconds = (int)streamer.progress;
hours = totalSeconds / (60 * 60);
if (hours > 0)
formattedTimeString = [NSString stringWithFormat:#"%d:", hours]; // WRONG
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
[formattedTimeString stringByAppendingFormat:#"%d:%d", minutes, seconds]; // WRONG
Basically I want it to appear as "3:35" for example to show 3 minutes, 35 seconds. I only want to show the hour section if it has been an hour, in which case it would be "2:3:35" for example (Can anyone recommend a better way to format this?).
The problem I am having is where I actually create/set the string (The lines tagged WRONG). Since this is being done every second, I would easily get a leak if I keep asking for a new string object. I figure I can solve this by releasing the foramttedTimeString at the end of the method, but is this the correct way to accomplish this? Would an NSMutableString help in any way? Is there a better, Cocoa way of doing this? I already asked in #iphonedev # freenode and they said I would have to write this method myself, but I figured I'd ask again.
To provide context: this is an internet radio streaming app (I know there are many already, but I'm just practicing). I want to be able to show the amount of time the stream has been playing for.
Sorry if this question is stupid, heh, like I said I'm new to this.
I would do it something like:
int totalSeconds = (int)streamer.progress;
hours = totalSeconds / (60 * 60);
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
if ( hours > 0 ) {
formattedTimeString = [NSString stringWithFormat:#"%d:%02d:%02d", hours, minutes, seconds];
} else {
formattedTimeString = [NSString stringWithFormat:#"%d:%02d", minutes, seconds];
}
Now at the end, formattedTimeString is the desired time, but you do not "own" it - you must retain it, or store it in a "copy" property if you wish to keep it around.
Note that the %02d gives you a guarenteed two digits, zero filled number, which is usually what you want for numbers in parts of times.
To see how you would do it with stringByAppendingFormat, it would look something like this:
NSString* formattedTimeString = #"";
if ( hours > 0 ) {
formattedTimeString = [formattedTimeString stringByAppendingFormat:#"%d:", hours];
}
formattedTimeString = [formattedTimeString stringByAppendingFormat:#"%d:%02d", minutes, seconds];
However in this case, you'll get times like 3:4:05, rether than a more desirable 3:04:05.
Note that formattedTimeString is being overwritten each time, but that is OK bvecause you do not "own" it at any time, so you are not responsible for releasing it.
Finally, to see it with a mutable string, it might look like this:
NSMutableString* formattedTimeString = [NSMutableString string];
if ( hours > 0 ) {
[formattedTimeString appendFormat:#"%d:", hours];
}
[formattedTimeString appendFormat:#"%d:%02d", minutes, seconds];
Again, the time result is the undesirable 3:4:05, and again you do not own formattedTimeString at the end, so it must be retained or stored with a copy property to keep it around.
For knowing the deltas as time units, you can also do something like this:
// as part of init...
self.gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// in the timer or wherever you are tracking time deltas...
static NSUInteger unitFlags =
NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:myBaseTime
toDate:[NSDate date] options:0];
Then you can reference the parts with something like this [components minute].
Remember, you'll have to release the calendar in dealloc.
Your code looks pretty good. You're not leaking any memory because the string objects you create have a retain count of zero and will be cleaned up by the system. However, if formattedTimeString is not a local variable in your function, you need to retain it at the end to prevent this from happening! To do that, you would add [formattedTimeString retain] to the end of your code block, and then before replacing the string object you would add [formattedTimeString release].
As a general rule, functions with names containing "alloc", "copy", "create", and "new" return objects that have already been retained, (meaning their retain count is +1). It's your responsibility to call release or autorelease on these objects when you're done using them - or they will just start piling up in memory.
Functions like "stringWithFormat:", "imageNamed:", and "arrayWithCapacity:" all return objects with a retain count of zero - so you can safely discard them (as you are in the code sample). If you want to keep them around, you should call retain to make sure they are not cleaned up while you're using them.
All that said, I think the main problem is your use of stringByAppendingFormat:. Since the NSString you're using isn't mutable, that call returns a new string. You'd want to say:
formattedTimeString = [formattedTimeString stringByAppendingFormat:#"%d:%d", minutes, seconds];
Alternatively, you could use an NSMutableString. Since this is something you'll be doing over and over again, I'd recommend doing that. Technically, either way is fine though.
Hope that helps! The whole retain/release thing can get confusing. Just remember that each object has a "retainCount" and once it hits zero there's no telling what happens to the object or it's data.
Hey thanks guys I appreciate the responses.
I ended up doing this, and it works, but I would like to know if you guys see any problems with it:
int totalSeconds = (int)streamer.progress;
[formattedTimeString setString:#""];
hours = totalSeconds / (60 * 60);
if (hours > 0)
[formattedTimeString appendFormat:#"%d:", hours];
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
[formattedTimeString appendFormat:#"%02d:%02d", minutes, seconds];
And then of course in viewDidLoad I instantiate the instance variable formattedTimeString:
formattedTimeString = [[NSMutableString alloc] initWithCapacity:8];
I did not do any retaining/releasing in the first code snippet because I didn't think it was necessary, but I could be wrong. I am, however, releasing in the dealloc method, so I should be fine there.