Desktop Core Location
Update 18/Feb/09 @ 19:45 EST: Source code is on BitBucket.org:
hg clone http://bitbucket.org/philippec/desktopcorelocation
Update 5/Feb/09 @ 12:43 EST: It appears that Apple may implement CoreLocation in their next generation desktop OS. Excellent!.
Update 8/Sep/08 @ 22:40 EST: The license is MIT. Share and enjoy!.
Update 8/Sep/08 @ 21:45 EST: This is an IronCoder entry, and is essentially a hack. I’m working on figuring out a license.
My IronCoder entry for c4[2]: a clean-room implementation of Apple’s CoreLocation.framework, complete with sample application.
http://developer.casgrain.com/files/DesktopCoreLocation.zip
Description
This is a clean-room implementation of Apple’s CoreLocation framework that is part of the iPhone SDK.
It uses Apple’s own headers, which are installed when you install the iPhone SDK, as the interface, and implements all the functionality of CoreLocation in an embeddable framework.
It can be made a system-wide framework buy changing its executable path from @loader_path/../Frameworks/
to /Library/Frameworks
.
The Desktop and Phone sample applications are very similar: they both demonstrate using CoreLocation.framework.
How it works
The framework figures out your current, internet-facing IP address using whatismyip.com. It then uses basic IP Geolocation web services to extract latitude and longitude. Results are cached 30 days for each IP address.
There are certainly other IP geolocation services (for instance, SkyHook Wireless) but they required a paid license.
Paranoïa
In keeping with the theme, you can drop a file called unauthorizedApps
in /Library/Documents/WebServer/clbl/
and start your webserver. You can then edit the file at will to deny a particular app the use of CoreLocation.
Contents
- PhoneLocation/PhoneLocation.xcodeproj
- Sample application that demonstrates using CoreLocation on the iPhone/iPod Touch.
Build and go, it will find your current location (which, in the Simulator, is 1, Infinite Loop, Cupertino, CA). Press the “Show Me” button to go to these coordinates in Google Maps.- DesktopLocation/DesktopLocation.xcodeproj
- Sample application that demonstrates using CoreLocation on the Desktop. It uses the Desktop CoreLocation framework in exactly the same manner as PhoneLocation, but the results are pulled from my version of the framework.
Press the “Show Me” button to go to these coordinates in Google Maps.- CoreLocation/CoreLocation.xcodeproj
- Stand-alone, embeddable framework
Requirements
- MacOSX 10.5
- Latest iPhone SDK. Does not contain any Apple proprietary information.
- Internet connexion
It might be interesting to extend the implementation to support a GPS device, if available.
Definitely! This is a one-weekend hack (the way IronCoder should be). Feel free to improve on it!
This is an awesome idea. Good work!
-W
Thanks! Everybody please be sure to file a Radar with Apple to ask for Core Location to be supported on the desktop (or really, where it’s really useful is a laptop). If enough people explain how useful it can be for road-warriors, we might get a very accurate official implementation in Snow Leopard…
Very cool, great job!
What license has this been released under? I didn’t see it in the zip anywhere.
Philippe,
I work for Skyhook and just wanted to correct your statement that we require a paid license. We offer an SDK to any developer who wants to integrate it into an application. You can get the SDK here: http://www.skyhookwireless.com/developers
We think this is a great project and we are happy to help out in any way we can. Feel free to email me directly — rsarver skyhookwireless com — if you have any questions.
Best, rs
I’m curious about the pattern used in the CoreLocation implementation files – specifically, the internal object that is being held on to by instances of those classes. What’s going on here – is it for thread-safety, or something else, or is it just a matter of programming style? Finally, is it common in Cocoa, or is this a somewhat unusual usage?
Erik,
It’s one way to do a public interface. Essentially, it’s an Abstract Factory (see http://en.wikipedia.org/wiki/Abstract_factory_pattern ). Your implementation of the class must then implement all that is declared, and usually a bit more (private stuff).
You could do the same thing with protocols, or (in C++) with pure virtual classes, but in this case the design was dictated by Apple’s headers. I just followed their lead.
Jesse,
Thanks for reminding me about the license. I’m working on it.
Why not use the iPhone as GPS device and build an IP connection using CoreLocation on the phone sending the data to the DesktopCoreLocation framework. Could be done in various stages like the phone does with carrier locating when GPS is not available yet.
Tom,
The whole thing came about because I don’t have an iPhone and if you use CoreLocation in the Simulator (see PhoneLocation.xcodeproj in the zip file), it reports your location as 1, Infinite Loop, Cupertino, CA…
Your presentation was great! Go Canada!
You couldn’t give us an Application demo without having to build it?
msr:
That’s correct. The projects build out of the box, and adding a built app to the zip file more than doubles its size.
Some notes:
– in performSelectorOnMainThread:withObject:, both the receiver and the object are retained. That means you don’t have to do the retain/release dance you’re currently doing.
– your internal object has all its properties marked “assign”. That’s almost certainly not what you want. Specifically, the delegate should be assign, all others should be retain or copy. You’ll have to add a dealloc method, but the rest of your code will be much simpler (e.g. in updateLocation: you won’t have to worry about that ipAddress var which is currently only valid by sheer luck).
Generally, you want to copy any possibly mutable objects (specifically strings), retain all noncopyable objects (like NSThread), and assign only delegates, data sources and the like.
– likewise, is there any reason internal isn’t a property?
HTH, and nice work!,
Johannes
If you’re running it on a system that isn’t online at the moment, you could fall back on the less precise “nearest major city” stored by Mac OS X:
BOOL GetCityLatLong(Location *outLocation) {
id city = [[NSUserDefaults standardUserDefaults] objectForKey: @”com.apple.TimeZonePref.Last_Selected_City”];
if (city && [city isKindOfClass: [NSArray class]] && [city length] >= 2) {
/* First two elements are the L/L. */
if (outLocation) {
outLocation->latitude = [[city objectAtIndex: 0] doubleValue];
outLocation->longitude = [[city objectAtIndex: 1] doubleValue];
}
return YES;
}
return NO;
}
And, I should say, you can listen for @”NSSystemTimeZoneDidChangeDistributedNotification” distributed notifications and update your reported location when they occur.
Johannes,
Thanks for taking some time and looking at my code! I guess my inexperience with these newfangled properties shows a little…
For performSelectorOnMainThread:withObject:, you are correct. The retain/release cycle was unnecessary, so I removed it.
In the case of the internal object’s properties, I followed your advice about copy/retain, but I wonder why I would need a -dealloc method. Shouldn’t @synthesize do all of this for me, call -release when a property is retain for instance? Furthermore, properties that are not NSObjects should be assign, as you can’t copy or retain simple types (float, int…).
Тоже думаю добавить в закладки, интересный блог.