[iOS][Web]iPhoneアプリケーションとサーバ間の通信(その1)
Ruby on Rails環境があると便利と聞いたし、OS Xにはインストール済みと聞いたので確認した。
$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]
$ gem -v
1.3.6
$ rails -v
Rails is not currently installed on this system. To get the latest version, simply type:
$ sudo gem install rails
You can then rerun your "rails" command.
最新のOS Xではrailsは自分でインストールとの事のようなので、素直にこのコマンドを実行した。
$ sudo gem install rails
Password:
********************************************************************************
\ MultiJson.encode is deprecated and will be removed in the next major version.
\ Use MultiJson.dump instead.
MultiJson.decode is deprecated and will be removed in the next major version.
Use MultiJson.load instead.
MultiJson.engine is deprecated and will be removed in the next major version.
Use MultiJson.adapter instead.
MultiJson.engine= is deprecated and will be removed in the next major
\ version. Use MultiJson.use instead.
MultiJson.default_engine is deprecated and will be removed in the next major
version. Use MultiJson.default_adapter instead.
********************************************************************************
Building native extensions. This could take a while...
Depending on your version of ruby, you may need to install ruby rdoc/ri data:
<= 1.8.6 : unsupported
= 1.8.7 : gem install rdoc-data; rdoc-data --install
= 1.9.1 : gem install rdoc-data; rdoc-data --install
>= 1.9.2 : nothing to do! Yay!
Successfully installed i18n-0.6.0
Successfully installed multi_json-1.3.2
Successfully installed activesupport-3.2.3
Successfully installed builder-3.0.0
Successfully installed activemodel-3.2.3
Successfully installed rack-1.4.1
Successfully installed rack-cache-1.2
Successfully installed rack-test-0.6.1
Successfully installed journey-1.0.3
Successfully installed hike-1.2.1
Successfully installed tilt-1.3.3
Successfully installed sprockets-2.1.3
Successfully installed erubis-2.7.0
Successfully installed actionpack-3.2.3
Successfully installed arel-3.0.2
Successfully installed tzinfo-0.3.33
Successfully installed activerecord-3.2.3
Successfully installed activeresource-3.2.3
Successfully installed mime-types-1.18
Successfully installed polyglot-0.3.3
Successfully installed treetop-1.4.10
Successfully installed mail-2.4.4
Successfully installed actionmailer-3.2.3
Successfully installed rake-0.9.2.2
Successfully installed thor-0.14.6
Successfully installed rack-ssl-1.3.2
Successfully installed json-1.7.0
Successfully installed rdoc-3.12
Successfully installed railties-3.2.3
Successfully installed bundler-1.1.3
Successfully installed rails-3.2.3
31 gems installed
Installing ri documentation for i18n-0.6.0...
Installing ri documentation for multi_json-1.3.2...
Installing ri documentation for activesupport-3.2.3...
Installing ri documentation for builder-3.0.0...
Installing ri documentation for activemodel-3.2.3...
Installing ri documentation for rack-1.4.1...
Installing ri documentation for rack-cache-1.2...
Installing ri documentation for rack-test-0.6.1...
Installing ri documentation for journey-1.0.3...
Installing ri documentation for hike-1.2.1...
Installing ri documentation for tilt-1.3.3...
Installing ri documentation for sprockets-2.1.3...
Installing ri documentation for erubis-2.7.0...
Installing ri documentation for actionpack-3.2.3...
Installing ri documentation for arel-3.0.2...
Installing ri documentation for tzinfo-0.3.33...
Installing ri documentation for activerecord-3.2.3...
Installing ri documentation for activeresource-3.2.3...
Installing ri documentation for mime-types-1.18...
Installing ri documentation for polyglot-0.3.3...
Installing ri documentation for treetop-1.4.10...
Installing ri documentation for mail-2.4.4...
Installing ri documentation for actionmailer-3.2.3...
Installing ri documentation for rake-0.9.2.2...
Installing ri documentation for thor-0.14.6...
Installing ri documentation for rack-ssl-1.3.2...
Installing ri documentation for json-1.7.0...
Installing ri documentation for rdoc-3.12...
Installing ri documentation for railties-3.2.3...
Installing ri documentation for bundler-1.1.3...
Installing ri documentation for rails-3.2.3...
Installing RDoc documentation for i18n-0.6.0...
Installing RDoc documentation for multi_json-1.3.2...
Installing RDoc documentation for activesupport-3.2.3...
Installing RDoc documentation for builder-3.0.0...
Installing RDoc documentation for activemodel-3.2.3...
Installing RDoc documentation for rack-1.4.1...
Installing RDoc documentation for rack-cache-1.2...
Installing RDoc documentation for rack-test-0.6.1...
Installing RDoc documentation for journey-1.0.3...
Installing RDoc documentation for hike-1.2.1...
Installing RDoc documentation for tilt-1.3.3...
Installing RDoc documentation for sprockets-2.1.3...
Installing RDoc documentation for erubis-2.7.0...
Installing RDoc documentation for actionpack-3.2.3...
Installing RDoc documentation for arel-3.0.2...
Installing RDoc documentation for tzinfo-0.3.33...
Installing RDoc documentation for activerecord-3.2.3...
Installing RDoc documentation for activeresource-3.2.3...
Installing RDoc documentation for mime-types-1.18...
Installing RDoc documentation for polyglot-0.3.3...
Installing RDoc documentation for treetop-1.4.10...
Installing RDoc documentation for mail-2.4.4...
Installing RDoc documentation for actionmailer-3.2.3...
Installing RDoc documentation for rake-0.9.2.2...
Installing RDoc documentation for thor-0.14.6...
Installing RDoc documentation for rack-ssl-1.3.2...
Installing RDoc documentation for json-1.7.0...
Installing RDoc documentation for rdoc-3.12...
Installing RDoc documentation for railties-3.2.3...
Installing RDoc documentation for bundler-1.1.3...
Installing RDoc documentation for rails-3.2.3...
自分と同様に何がおこるのか不安な人の為に全てのログを載せた。
最初、パスワード入力後、何も返ってこない状況が暫く続いたので不安だったが、上手くいったようだ。
再度、railsコマンドで確認してみる。
$ rails -v
Rails 3.2.3
上手くいったようだ。今回は、ここまで。
[iOS]GPSとGPX(その2)
前回は、iOS GPX Frameworkの使い方は何となく分かったが、それをGPXファイルとして保存するには、どうすればいいのか分からなくて困っていた。ソースコードを眺めてみて何となく分かってきた。GPXElementクラスが基本の様相だ。それのプロパティgpxはNSString型だ。どうやら、ここからGPXファイルのデータを取得するようだ。
以下は公式サイトのサンプル・コードそのものだ。
- (void)viewDidLoad
{
[super viewDidLoad];
GPXRoot *root = [GPXRoot rootWithCreator:@"Sample Application"];
GPXWaypoint *waypoint = [root newWaypointWithLatitude:35.658609f longitude:139.745447f];
waypoint.name = @"Tokyo Tower";
waypoint.comment = @"The old TV tower in Tokyo.";
GPXTrack *track = [root newTrack];
track.name = @"My New Track";
[track newTrackpointWithLatitude:35.658609f longitude:139.745447f];
[track newTrackpointWithLatitude:35.758609f longitude:139.745447f];
[track newTrackpointWithLatitude:35.828609f longitude:139.745447f];
NSLog(@"%@", root.gpx);
}
以下は、デバッグ出力の例だ。ちゃんと、GPXになっているようだ。
<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" creator="Sample Application">
<wpt lat="35.658607" lon="139.745453">
<name>Tokyo Tower</name>
<cmt>The old TV tower in Tokyo.</cmt>
</wpt>
<trk>
<name>My New Track</name>
<trkseg>
<trkpt lat="35.658607" lon="139.745453">
</trkpt>
<trkpt lat="35.758610" lon="139.745453">
</trkpt>
<trkpt lat="35.828609" lon="139.745453">
</trkpt>
</trkseg>
</trk>
</gpx>
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/WayPoints - GitHub
関連情報
iOS GPX Framework
GitHub
This is a iOS framework for parsing/generating GPX files. This Framework parses the GPX from a URL or Strings and create Objective-C Instances of GPX structure.
[iOS]GPSとGPX(その1)
GPSの情報を扱う形式に、GPX(GPS eXchange Format)というものがある。これを扱う為のフレームワークがMITライセンスで後悔されていたので、使ってみた。
iOS GPX Framework
http://gpxframework.com/
GitHubでの説明は、これをフレームワーク化して組み込み手順となっていたが、あまり、Xcodeに知らないものを組み込みたくないので、ソース一式をプロジェクトに追加した。
ヘッダーファイルの検索パスに、このフレームワークのソースを追加する。
これで以下のようなサンプル・コードのビルドが通るようになったと思う。
#import <GPX/GPX.h>
...
GPXRoot *root = [GPXRoot rootWithCreator:@"Sample Application"];
GPXWaypoint *waypoint = [root newWaypointWithLatitude:35.658609f longitude:139.745447f];
waypoint.name = @"Tokyo Tower";
waypoint.comment = @"The old TV tower in Tokyo.";
GPXTrack *track = [root newTrack];
track.name = @"My New Track";
[track newTrackpointWithLatitude:35.658609f longitude:139.745447f];
[track newTrackpointWithLatitude:35.758609f longitude:139.745447f];
[track newTrackpointWithLatitude:35.828609f longitude:139.745447f];
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/WayPoints - GitHub
関連情報
iOS GPX Framework
GitHub
This is a iOS framework for parsing/generating GPX files. This Framework parses the GPX from a URL or Strings and create Objective-C Instances of GPX structure.
[iOS]データ管理(その3)
独自のデータ管理の仕組みの用意している者にとっては、少し厄介なNSFetchedResultsControllerについて、すこし、考えてみる。
NSFetchedResultsControllerはテーブル・ビューでの利用を想定したコントローラのクラスだ。
ViewControllerクラスのNSFetchedResultsControllerを生成しているコードは以下の通り。
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil) return __fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
return __fetchedResultsController;
}
対象となるデータ(管理オブジェクト)を『Event』に、整列のキーを『timeStamp』と設定して、生成する。
そして、NSFetchedResultsControllerからテーブルに設定する項目を得ているので、NSFetchedResultsControllerは一覧表示する項目を管理するものといえる。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[object valueForKey:@"timeStamp"] description];
}
そして、データが更新される。つまり、管理オブジェクト・コンテキストに変更が発生すると、委任の仕組みでそれを通知してくる。
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Datum - GitHub
関連情報
Core Data Programming Guide
Developerサイトの情報。
[iOS]データ管理(その2)
MainStoryboard.storyboardの中身を空にして、Navigation Controllerを配置する。デフォルトで、テーブル・ビューが組み込まれているので、これを利用する。
Root View ControllerのCustom Classを自分のViewControllerに変更する(説明の順番が前後してしまったが、自分のViewControllerの親クラスをUITableViewControllerに変更しておく必要はあると思う)。
そして、Table View CellのIdentifierをCellに変更しておく。このIdentifierを後のコードで利用するので。
独自のViewControllerクラスのヘッダーをテーブル・ビューとCoreDataに対応させる。
@interface ViewController : UITableViewController &tl;NSFetchedResultsControllerDelegate≷
@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@end
AppDelegateクラスの、アプリケーション起動時に呼ばれるメソッドで、管理オブジェクト・コンテキストをビュー・コントローラーに渡すコードを追加する。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
ViewController *controller = (ViewController *)navigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
return YES;
}
ViewControllerクラスの、CoreDataとテーブル・ビュー対応のコードは、雛形のコードをほぼそのまま流用している。現在のXcodeの新規プロジェクトで生成される雛形のコードでは、NSFetchedResultsControllerが使われていて、データとテーブル・ビューの連動が自動で行われて便利だが、独自のデータ管理の仕組みを持っている場合、それを介さないでコントロールされるので、これについては、今後の課題と考えている。
@interface ViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
@end
@implementation ViewController
@synthesize fetchedResultsController = __fetchedResultsController;
@synthesize managedObjectContext = __managedObjectContext;
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self action:@selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
}
…
- (void)insertNewObject:(id)sender
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name]
inManagedObjectContext:context];
[newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id sectionInfo = [[self.fetchedResultsController sections]
objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil) {
return __fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
return __fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[object valueForKey:@"timeStamp"] description];
}
@end
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Datum - GitHub
関連情報
Core Data Programming Guide
Developerサイトの情報。
[iOS]データ管理(その1)
独自にデータ管理をDocumentクラスで行っている著者としては、CoreDataとの付き合いは悩む部分がある。今回は曖昧にしていた部分をしっかり理解できる様、シンプルな構成のプロジェクトにCoreDataを組み込んでゆく。
プリコンパイル・ヘッダーDatum-Prefix.pchにCoreDataのヘッダーを追加する。
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#endif
アプリケーションのコントローラとなるAppDelegateに、CoreData関連のプロパティとメソッドを追加する。
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
そして、AppDelegateにCoreData関連のコードを追加する。
アプリケーション終了時に保存。
- (void)applicationWillTerminate:(UIApplication *)application
{
[self saveContext];
}
突然、アプリケーションが停止される事を考えて、バックグラウンドに回った際にも保存する等、工夫する余地はあると思う。
保存のメソッドだ。
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
これは雛形で用意されるメソッドそのままだが、abort()関数の呼び出しは、マズイと思う。リジェクトもされるのでは?
雛形のコードは巧妙で、プロパティ呼び出しが、メソッド呼び出しになっていて、必要なタイミングで生成されるようになっている。
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Datum" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Data.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
SQLiteファイルの保存先を返すメソッド。ただ、Documentディレクトリでいいのか?隠すように場所でもいいのでは?という疑問はある。
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
モデルを定義したファイルDatum.xdatamodeldは、とりあえず、雛形で用意されるファイルのコピーだ。
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Datum - GitHub
関連情報
Core Data Programming Guide
Developerサイトの情報。
[iOS]地図を扱う
地図を表示するのは簡単だ。MapKitフレームワークをプロジェクトに追加し、MapKit/MapKit.hをインポートする。そして、以下のコードで地図は表示される。
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect rect = CGRectMake(10.0, 80.0, 300.0, 300.0);
self.mapView = [[MKMapView alloc] initWithFrame:rect];
[self.view addSubview:self.mapView];
}
- (void)viewDidUnload
{
self.mapView = nil;
[super viewDidUnload];
}
viewDidLoadメソッドに以下のコードを追加すると、指定した緯度経度が表示される。
MKCoordinateRegion region = {{34.406944, 133.195462}, {1.0, 1.0}};
[self.mapView setRegion:region animated:NO];
以下のコードで、ピンが追加される。
@interface ViewController : UIViewController
@property (strong, nonatomic) MKMapView *mapView;
@end
@interface Annotation : NSObject
@property (strong, nonatomic) NSString *name;
@property (assign, nonatomic) CLLocationCoordinate2D coordinate;
- (id)initWithName:(NSString *)name latitude:(double)latitude longitude:(double)longitude;
@end
@implementation Annotation
@synthesize name = _name;
@synthesize coordinate = _coordinate;
- (id)initWithName:(NSString *)name latitude:(double)latitude longitude:(double)longitude
{
if ((self = [super init]) != nil) {
CLLocationCoordinate2D coordinate;
coordinate.latitude = latitude;
coordinate.longitude = longitude;
self.coordinate = coordinate;
self.name = name;
}
return self;
}
- (NSString *)title
{
return self.name;
}
- (void)dealloc
{
self.name = nil;
}
@end
@implementation ViewController
@synthesize mapView = _mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect rect = CGRectMake(10.0, 80.0, 300.0, 300.0);
self.mapView = [[MKMapView alloc] initWithFrame:rect];
[self.view addSubview:self.mapView];
MKCoordinateRegion region = {{34.406944, 133.195462}, {1.0, 1.0}};
[self.mapView setRegion:region animated:NO];
Annotation *annotation = [[Annotation alloc] initWithName:@"土堂小学校"
latitude:34.406944
longitude:133.195462];
[self.mapView addAnnotation:annotation];
}
- (void)viewDidUnload
{
self.mapView = nil;
[super viewDidUnload];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation
{
if (annotation == self.mapView.userLocation) {
return nil;
}
MKPinAnnotationView *pinAnnotationView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:@"pin"];
if (pinAnnotationView == nil) {
pinAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pin"];
}
else {
pinAnnotationView.annotation = annotation;
}
pinAnnotationView.pinColor = MKPinAnnotationColorRed;
pinAnnotationView.animatesDrop = YES;
pinAnnotationView.canShowCallout = YES;
return pinAnnotationView;
}
実行。
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Maps - GitHub
関連情報
iOSプログラミング逆引きリファレンス108 ~知りたいことがすぐわかるiPhoneプログラミングテクニック~
お勧めです。
[iOS]Tweeting(パブリックタイムライン)
今回は、DeveloperサイトのサンプルコードTweetingのコードのままだ。
パブリックタイムラインを取得して、それをNSLog()でデバッグ出力するだけだ。
- (IBAction)timeline:(id)sender
{
TWRequest *postRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"] parameters:nil requestMethod:TWRequestMethodGET];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *output;
if ([urlResponse statusCode] == 200) {
NSError *jsonParsingError = nil;
NSDictionary *publicTimeline = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonParsingError];
output = [NSString stringWithFormat:@"HTTP response status: %i\nPublic timeline:\n%@", [urlResponse statusCode], publicTimeline];
}
else {
output = [NSString stringWithFormat:@"HTTP response status: %i\n", [urlResponse statusCode]];
}
[self performSelectorOnMainThread:@selector(msgBox:) withObject:output waitUntilDone:NO];
}];
}
- (void)msgBox:(NSString *)text
{
self.msgBoxTextView.text = text;
}
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Tweets - GitHub
関連情報
iOS Twitter framework
Twitter Developersサイトの情報。
Tweeting
Developerサイトのサンプル・コード
[iOS]Tweeting(アカウント管理 2)
iOS5からのTwitter/Accounts frameworkの凄いところは、複数のアカウントを扱える事だ。DeveloperサイトのサンプルコードTweetingのコードに手を加えて、iOS機器に登録されているアカウントの全てでtweetするようにしてみた。
- (IBAction)tweet2:(id)sender
{
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
if(granted) {
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
for (NSUInteger i = 0; i < [accountsArray count]; i++) {
ACAccount *twitterAccount = [accountsArray objectAtIndex:i];
NSLog(@"account: %@", twitterAccount);
TWRequest *postRequest = [[TWRequest alloc]
initWithURL:[NSURL URLWithString:@"http://api.twitter.com/1/statuses/update.json"]
parameters:[NSDictionary dictionaryWithObject:@"hello, world" forKey:@"status"]
requestMethod:TWRequestMethodPOST];
[postRequest setAccount:twitterAccount];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *output = [NSString stringWithFormat:@"HTTP response status: %i",
[urlResponse statusCode]];
NSLog(@"%@", output);
[self performSelectorOnMainThread:@selector(displayText:) withObject:output waitUntilDone:NO];
}];
}
}
}
登録されているアカウント分、同じ内容のtweetが投稿されている事が確認できると思う。無意味な内容なので迷惑だと思うが。
ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Tweets - GitHub
関連情報
iOS Twitter framework
Twitter Developersサイトの情報。
Tweeting
Developerサイトのサンプル・コード