GPSを使って位置情報を取得するサンプル。
まずは、GPSのデータ
ひとまず使いそうなものだけをピックアップしたクラス
GPSData.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
@interface GPSData : NSObject
{
CLLocationDegrees latitude_; // 緯度
CLLocationDegrees longitude_; // 経度
CLLocationDistance altitude_; // 高度
CLLocationAccuracy accuracy_; // 正確さ
}
- (id)initWithLatitude:(CLLocationDegrees) latitude
longitude:(CLLocationDegrees) longitude
altitude:(CLLocationDistance) altitude
accuracy:(CLLocationAccuracy) accuracy;
- (float)latitude;
- (void)setLatitude:(CLLocationDegrees)value;
- (float)longitude;
- (void)setLongitude:(CLLocationDegrees)value;
- (float)altitude;
- (void)setAltitude:(CLLocationDistance)value;
- (float)accuracy;
- (void)setAccuracy:(CLLocationAccuracy)value;
@end
GPSData.m
#import "GPSData.h"
@implementation GPSData
- (float)latitude
{
return (float)latitude_;
}
- (void)setLatitude:(CLLocationDegrees)value
{
latitude_ = value;
}
- (float)longitude
{
return (float)longitude_;
}
- (void)setLongitude:(CLLocationDegrees)value
{
longitude_ = value;
}
- (float)altitude
{
return (float)altitude_;
}
- (void)setAltitude:(CLLocationDistance)value
{
altitude_ = value;
}
- (float)accuracy
{
return (float)accuracy_;
}
- (void)setAccuracy:(CLLocationAccuracy)value
{
accuracy_ = value;
}
- (id)init
{
if (![super init]) return nil;
latitude_ = 0.0f;
longitude_ = 0.0f;
accuracy_ = 0.0f;
return self;
}
- (id)initWithLatitude:(CLLocationDegrees) latitude
longitude:(CLLocationDegrees) longitude
altitude:(CLLocationDistance) altitude
accuracy:(CLLocationAccuracy) accuracy
{
if (![self init]) return nil;
latitude_ = latitude;
longitude_ = longitude;
altitude_ = altitude;
accuracy_ = accuracy;
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"latitude = %f\nlongitude = %f\naltitude = %f\naccuracy = %f", latitude_, longitude_, altitude_, accuracy_];
}
@end
LocationTracker.h
次に位置情報を取得し続けるクラス。
これはシングルトン。
これはシングルトン。
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import "GPSData.h"
@protocol LocationTrackerDelegate
- (void)locationUpdated:(GPSData *)data;
@end
@interface LocationTracker : NSObject <CLLocationManagerDelegate>
{
CLLocationManager *locationManager_;
GPSData *data_;
BOOL isTracking_;
id<LocationTrackerDelegate> observer_;
}
- (GPSData *)current;
- (BOOL)toggleTracking;
- (BOOL)startTracking;
- (BOOL)stopTracking;
- (void)setObserver:(id<LocationTrackerDelegate>)observer;
+ (id)instance;
@end
@interface LocationTracker (privateMethods)
- (BOOL)allowedTracking;
@end
LocationTracker.m
#import "LocationTracker.h"
@implementation LocationTracker
static id _instance = nil;
- (GPSData *)current
{
return data_;
}
- (BOOL)toggleTracking
{
if (isTracking_) return [self stopTracking];
return [self startTracking];
}
- (BOOL)startTracking
{
if (![self allowedTracking]) return NO;
isTracking_ = YES;
[locationManager_ startUpdatingLocation];
return YES;
}
- (BOOL)stopTracking
{
isTracking_ = NO;
[locationManager_ startUpdatingLocation];
return YES;
}
- (id)init
{
if (![super init]) return nil;
locationManager_ = [[CLLocationManager alloc] init];
locationManager_.delegate = self;
isTracking_ = NO;
data_ = [[GPSData alloc] init];
observer_ = nil;
return self;
}
- (void)setObserver:(id<LocationTrackerDelegate>)observer
{
observer_ = observer;
}
- (void)dealloc
{
[locationManager_ release];
[super dealloc];
}
+ (id)instance
{
@synchronized(self) {
if (!_instance) {
[[self alloc] init];
}
}
return _instance;
}
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (!_instance) {
_instance = [super allocWithZone:zone];
return _instance;
}
}
return nil;
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)returnCount
{
return UINT_MAX;
}
- (void)release
{
}
- (id)autorelease
{
return self;
}
@end
@implementation LocationTracker (privateMethods)
- (BOOL)allowedTracking
{
return [CLLocationManager locationServicesEnabled];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[data_ initWithLatitude:newLocation.coordinate.latitude
longitude:newLocation.coordinate.longitude
altitude:newLocation.altitude
accuracy:newLocation.horizontalAccuracy];
if (observer_) {
[observer_ locationUpdated:data_];
}
}
@end
使い方
- (void)start
{
[[LocationTracker instance] setObserver:self];
[[LocationTracker instance] startTracking];
}
- (void)stop
{
[[LocationTracker instance] stopTracking];
}
- (void)locationUpdated:(GPSData *)data
{
// 位置が変わった時に呼ばれる
}
RubyみたいにDate.todayとかが使いたかったので拡張してみた。
NSDateExtension.h
#import <Foundation/Foundation.h> @interface NSDate(exDateMethods) + (NSDate *)now; + (NSDate *)today; - (NSDate *)daysAgo:(unsigned int)days; - (NSDate *)daysAfter:(unsigned int)days; - (NSDate *)hoursAgo:(unsigned int)hours; - (NSDate *)hoursAfter:(unsigned int)hours; - (NSDate *)next; - (NSDate *)prev; - (NSString *)format:(NSString *)format; - (NSString *)strftime:(NSString *)format; - (BOOL)laterThan:(NSDate *)date; @end
NSDateExtension.m
#import "NSDateExtension.h"
@implementation NSDate(exDateMethods)
+ (NSDate *)now
{
return [NSDate date];
}
+ (NSDate *)today
{
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setTimeStyle : NSDateFormatterNoStyle];
[formatter setDateStyle : NSDateFormatterMediumStyle];
NSString *todayString = [formatter stringFromDate:[NSDate date]];
return [formatter dateFromString:todayString];
}
- (NSDate *)daysAgo:(unsigned int)days
{
return [self initWithTimeInterval:-1.0 * days * 24 * 60 * 60 sinceDate:self];
}
- (NSDate *)daysAfter:(unsigned int)days
{
return [self initWithTimeInterval:days * 24 * 60 * 60 sinceDate:self];
}
- (NSDate *)hoursAgo:(unsigned int)hours
{
return [self initWithTimeInterval:-1.0 * hours * 60 * 60 sinceDate:self];
}
- (NSDate *)hoursAfter:(unsigned int)hours
{
return [self initWithTimeInterval:hours * 60 * 60 sinceDate:self];
}
- (NSDate *)next
{
return [self daysAfter:1];
}
- (NSDate *)prev
{
return [self daysAgo:1];
}
- (NSString *)format:(NSString *)format
{
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:format];
return [formatter stringFromDate:self];
}
- (NSString *)strftime:(NSString *)format
{
return [self format:format];
}
- (BOOL)laterThan:(NSDate *)date
{
if ([self timeIntervalSinceDate:date] < 0) return YES;
return NO;
}
@end
main.m
#import <Foundation/Foundation.h>
#import "NSDateExtension.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSDate *today = [NSDate today];
NSDate *yesterday = [today prev];
NSDate *now = [NSDate now];
NSLog(@"%@", today);
NSLog(@"%@", [today next]);
NSLog(@"%@", [today prev]);
NSLog(@"%@", now);
NSLog(@"%@", [now next]);
NSLog(@"%@", [now prev]);
NSLog(@"%@", [now strftime:@"hh:mm:ss"]);
NSLog(@"%@", [now format:@"hh:mm:ss"]);
NSLog(@"%d", [now laterThan:yesterday]);
[pool drain];
return 0;
}
http://d.hatena.ne.jp/WaterFlea/20091011/1255242225
を参考にさせてもらい、NSStringを拡張して、実装。
Crypto.h
#import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> @interface NSData(exDigest) + (NSData *)utf8Data: (NSString *)string; - (NSData *)sha1Digest; - (NSData *)md5Digest; - (NSString *)hexString; - (NSString *)sha1String; @end @interface NSString(exDigest) - (NSString *)sha1String; @end
Crypto.m
#import "Crypto.h"
@implementation NSData(exDigest)
+ (NSData *)utf8Data:(NSString *) string
{
const char* utf8str = [string UTF8String];
NSData* data = [NSData dataWithBytes: utf8str length: strlen(utf8str)];
return data;
}
- (NSData *)sha1Digest
{
unsigned char result[CC_SHA1_DIGEST_LENGTH];
CC_SHA1([self bytes], [self length], result);
return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH];
}
- (NSData *)md5Digest
{
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5([self bytes], [self length], result);
return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *)sha1String
{
return [[self sha1Digest] hexString];
}
- (NSString *)hexString
{
unsigned int i;
static const char *hexstr[16] = { "0", "1", "2", "3",
"4", "5", "6", "7",
"8", "9", "a", "b",
"c", "d", "e", "f" };
const char *dataBuffer = (char *)[self bytes];
NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([self length] * 2)];
for (i=0; i<[self length]; i++) {
uint8_t t1, t2;
t1 = (0x00f0 & (dataBuffer[i])) >> 4;
t2 = 0x000f & (dataBuffer[i]);
[stringBuffer appendFormat:@"%s", hexstr[t1]];
[stringBuffer appendFormat:@"%s", hexstr[t2]];
}
return [[stringBuffer copy] autorelease];
}
@end
@implementation NSString(exDigest)
- (NSString *)sha1String
{
return [[NSData utf8Data: self] sha1String];
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Crypto.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"%@", [[NSData utf8Data: @"test"] sha1String]);
NSLog(@"%@", [@"test" sha1String]);
[pool drain];
return 0;
}
比較的よく使うのでメモとしてエントリー
Singleton.h
#import <Foundation/Foundation.h>
@interface Singleton : NSObject {
}
+ (id)instance;
Singleton.m
@implementation Singleton
static id _instance = nil;
+ (id)instance
{
@synchronized(self) {
if (!_instance) {
[[self alloc] init];
}
}
return _instance;
}
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (!_instance) {
_instance = [super allocWithZone:zone];
return _instance;
}
}
return nil;
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)returnCount
{
return UINT_MAX;
}
- (void)release
{
}
- (id)autorelease
{
return self;
}
@end
ヘッダファイルは、Encrypt.hというファイル名で
#import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> @interface NSData(exDigest) + (NSData *) utf8Data: (NSString *) string; - (NSData *) sha1Digest; - (NSData *) md5Digest; - (NSString *) hexString; - (NSString *) sha1String; @end
mファイルは、Encrypt.mというファイル名で
#import "Encrypt.h"
@implementation NSData(exDigest)
+ (NSData *) utf8Data: (NSString *) string
{
const char* utf8str = [string UTF8String];
NSData* data = [NSData dataWithBytes: utf8str length: strlen(utf8str)];
return data;
}
- (NSData *) sha1Digest
{
unsigned char result[CC_SHA1_DIGEST_LENGTH];
CC_SHA1([self bytes], [self length], result);
return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH];
}
- (NSData *) md5Digest
{
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5([self bytes], [self length], result);
return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *) sha1String
{
return [[self sha1Digest] hexString];
}
- (NSString *)hexString
{
unsigned int i;
static const char *hexstr[16] = { "0", "1", "2", "3",
"4", "5", "6", "7",
"8", "9", "a", "b",
"c", "d", "e", "f" };
const char *dataBuffer = (char *)[self bytes];
NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([self length] * 2)];
for (i=0; i<[self length]; i++) {
uint8_t t1, t2;
t1 = (0x00f0 & (dataBuffer[i])) >> 4;
t2 = 0x000f & (dataBuffer[i]);
[stringBuffer appendFormat:@"%s", hexstr[t1]];
[stringBuffer appendFormat:@"%s", hexstr[t2]];
}
return [[stringBuffer copy] autorelease];
}
@end
実行用ファイルはmain.mとかってしてあげて
#import "Encrypt.h"
int main(void)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSString* str = @"test";
NSLog(@"%@", [[NSData utf8Data: str] sha1String]);
[pool release];
return 0;
}
コンパイル
$ gcc -c main.m -o main.o $ gcc -c Encrypt.m -o Encrypt.o $ gcc -o main main.o Encrypt.o -framework Foundation
そして、実行してみる。
$ ./main 2010-04-10 15:18:51.372 main[1712:903] a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
といった感じで、sha1成功。
Macにも慣れてきたので、少しやってみました。
Objective-Cの書き方がいまいちしっくりこないけど、それなりにちまちま作ってます。
ページ遷移や、データ保持、内蔵ブラウザ
とかは、それっぽく動くようになりました。
あとは、サーバ側のAPIを作らないと進めなくなったので一時中断w

最新コメント