なんか仕事疲れたわ〜もう何も考えたくないわ〜って時にやると癒やされるゲーム。瀬戸弘司が紹介してて知った。
ゲームオーバーが無いから無心になれる
ねこあつめみたいに、とくになにか敵にやられて死ぬとかが無い。だからボーっとやれる。
ゲームの趣旨は、彗星をミサイルとかビームで破壊してエネルギーを貯めて、そのエネルギーで星を緑化するというもの。
らーめんを愛するすべての人に捧ぐ!
ありそうでなかったらーめん屋推薦アプリです。
名前は『麺利き』。
食べておいしかったらーめん、ありますよね。
その写真をアプリに入力してください。
すると、アプリが似た雰囲気のらーめんを出すラーメン屋を探します。
例えば、野菜たっぷりのらーめんを入力すると・・
見事に二郎系のらーめん屋が提示されましたwww
ぜひ、みなさんのお気に入りらーめんで試してみてください。
きっといいお店が見つかりますよ!
開発には、最近何かと話題のディープラーニングという機械学習アルゴリズムの一つを使用しました。
推薦アルゴリズムのために、30万枚のらーめん画像を集めて学習させました。
つまり、このアプリは「らーめんとは何か」を理解しているのです!(どーん)
開発の裏話はまた別のエントリで書きますので、お楽しみに!!
Appleから受け取ったクラッシュログは、クラッシュした状態のスタックトレースをバイナリ上のアドレスで示されています。
このままだと、内容を見てもソースコード上のどこが悪いのかさっぱり分かりません。
シンボリケートとは、主にバイナリ上のアドレスからソースコードの場所を突き止める事をいいます。
クラッシュログのシンボリケートにはsymbolicatecrash
コマンドを使用すると便利です。
XCode 6では以下のパスに存在しています。
/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash
/usr/bin
あたりにシンボリックリンクを貼っておくと吉。
クラッシュログを吐いたバイナリと同じビルドのもので、以下が必要です:
XCodeのOrganizerを開き、アーカイブ一覧から該当のビルドを探します。
次に、該当ビルドの項目を右クリックしてShow in Finder
します。
開かれたディレクトリに、上記二つのファイルが存在します。
以下のように実行します。
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
symbolicatecrash -v crashファイル dSYMファイル appファイル
DEVELOPER_DIR
を予め設定しておかないと、以下のようなエラーが出ます。
Error: "DEVELOPER_DIR" is not defined at /Applications/Xcode.app/[snip]Resources/symbolicatecrash line 53.
新言語Swiftでは、C++のようにカスタムのオペレータを定義できます。
このオペレータには、Unicodeの文字が使えるとのこと!
下記のツイートのような感じで使えるらしいです。
let r = ¬(a ∧ b)
詳しい例はこちら:
Google Drive, Docs, SheetsのiOS版では、アプリ間でGoogleアカウント情報を共有しています。
いずれかのアプリで一度認証すれば、他のアプリでは面倒な認証手順が不要になります。
これはどういう仕組みで行われているのでしょう?
アプリはどのようにして、ユーザの入力無しにユーザを識別しているのでしょう。
実は、先に述べたGoogleのアプリ達は、KeychainというOSの仕組みを使っています。
Keychainは、もしあなたがMac OSXユーザであればなじみ深いと思います。実はiOSにも備わっています。
これは、パスワードや秘密鍵、証明書などの機密情報を安全に管理するための仕組みです。
Keychainで保管されるデータは暗号化されます。
Keychainと同じようにユーザ情報を保存するための仕組みとして、UserDefaultsというものがあります。
UserDefaultsは、主にプリファレンスなどを保存するための仕組みです。
UserDefaultsと比べて、Keychainが機密情報の取り扱いに優れている点は以下です:
Keychain Access Group
に属するアプリ同士でアクセスできる (Keychain Access Group
は後ほど詳しく説明します)Keychain Servicesは、Keychainを使うためのAPI群です。
以下からAppleのドキュメントを参照できます:
Mac OSXとiOSではAPIが異なるので注意です。
ここでは、iOSでの使用を前提として説明します。
日本語の資料では以下が参考になります。
しかしながら上記ページは古くて、XCode上の手順が有効でない部分があります。
本ページでは、XCode 5で設定する場合を説明します。
利用するには、Security.framework
をプロジェクトに追加してください。
Appleが用意したAPIをそのまま使うのもいいですが、我々には時間がありません。
オススメは LUKeychainAccess です。
LUKeychainAccess
を使えば、NSUserDefaults
と同じ感覚でKeychainのアイテムを管理できます。
以降は、このラッパを使う前提で説明します。
NSUserDefaults
と全く同じです。
[[LUKeychainAccess standardKeychainAccess] setBool:NO forKey:@"authorized"];
BOOL authorized = [[LUKeychainAccess standardKeychainAccess] boolForKey:@"authorized"];
制御の軸はアイテムに「いつ」アクセスできるのかと、「どれが」アクセスできるのか、の2つがあります。
アプリケーションが「いつ」アクセスできるのかを制御します。詳しくはこちら。
LUKeychainAccess
では、それぞれ以下の定数で指定できます。
以下のように指定します。
LUKeychainAccess* keychainAccess = [LUKeychainAccess standardKeychainAccess];
keychainAccess.accessibilityState = LUKeychainAccessAttrAccessibleWhenUnlocked;
「どの」アプリケーションがアイテムにアクセスできるのかを制御します。
デフォルトでは、アクセスできるアプリケーションはそのアイテムを格納したアプリケーション自身だけです。
グループの指定によって、同じグループに属するアプリケーションからのアクセスを許可出来ます。
このグループは、アイテムごとに指定できます。
例えば、あなたのapplication-identifier
がcom.foobar.application
だとします。
あなたのアプリケーションが読み書き可能なグループは、そのグループ識別子がapplication-identifier
に前方一致する場合です。
グループによる権限の違いは以下の通りです。
com.foobar.application
com.foobar
com.apple.calendar
com.foobar.mailer
つまり、com.foobar
というグループに属するアイテムを作成すると、アクセス出来るアプリケーションはapplication-identifier
がcom.foobar.*
に相当するものになります。
また、注意点ですが、同じグループに属していてもアクセスできない場合があります。
それは、Code Signing Identity
がアプリケーション間で異なる場合です。
つまり、アイテムを共有するアプリケーションは同一ベンダーのものでなければなりません。
Keychain Access Groupをデフォルトのapplication-identifier
から変更するには、Entitlementsを作成します。
XCode 5ではこの作成手順が簡単になっています。
まず、ビルドターゲットのCapabilitiesタブを開きます。
Keychain Sharingという項目を見つけたら、スイッチをONにしましょう。
Keychain Groupsというリストが現れたはずです。
ここに、指定したいグループの識別子を入力します。
グループは複数指定できます。
一番上に記述したものが、デフォルトで使用されるグループになります。
シミュレータでも動作しますが、テストは実機でやる事を強くおすすめします。
というのは、シミュレータだと常にグループがtest
となるからです。
シミュレータ上では、グループ指定に関わらず全てのアプリケーションから全てのアイテムにアクセス出来ます。
ここで、TestFlight経由でインストールしたビルドと、USB経由でインストールしたビルドのapplication-identifier
を別々にすればテストできるかもしれないと思いますが、これも無理です。
理由は、Code Signing Identity
が異なるからです。
共通のCode Signing Identity
で、異なるapplication-identifier
のアプリを用意しましょう。
基本的な使い方のセクションで説明した通り、アイテムのキーは単純な文字列で指定できます。
[[LUKeychainAccess standardKeychainAccess] setBool:NO forKey:@"authorized"];
これは以下のような単純なkey/valueストアです。
key = value
Keychain Servicesでは、この単純なキーに加えて、オプションでサービス名も付けられます。
以下のようにserviceディレクトリにkey/valueを格納していくイメージです。
service.key = value
サービス名の指定は、TwitterやFacebookの認証情報をセットにして格納したい場合に便利です。
残念ながらLUKeychainAccess
は、サービス名の指定にまだ対応していません。。
そこで、このラッパをフォークして対応させてみました。
サービス名対応版なら、以下のようにサービス名を指定できます。
[[LUKeychainAccess standardKeychainAccess] setBool:NO forKey:@"authorized" service:@"Twitter"];
BOOL authorized = [[LUKeychainAccess standardKeychainAccess] boolForKey:@"authorized" service:@"Twitter"];
簡単ですね!
本家にはこの拡張をプルリクエストしておきました。
iOSアプリにおいて、Core Dataは永続的で大きなオブジェクトグラフが取り扱えるモデルを提供する。
多くの有名アプリで使われているけど、複雑だしそのまま使おうとすると開発効率が悪い。
Core Dataを置き換えようとするライブラリが多くあるが、さらに多くのライブラリはCore Dataをよりよくしようとするものだ。
それらのライブラリは糖衣構文(シンタックスシュガー)からフルスタックのフレームワークまで幅広い。
本記事では、CoreDataを取り扱うオープンソースのライブラリを紹介する。
あなたのCore Data要件にマッチするものを見つけて下さい。
mogenerator |
Jonathan ‘Wolf’ Rentzsch |
http://ghbtns.com/github-btn.html?user=rentzsch&repo=mogenerator&type=watch&count=true |
ラッパーライブラリはいくつかの糖衣構文や便利メソッド群を提供するもの。
Core Dataの冗長で複雑なAPIを簡単にしてくれる。
例えば、新しいManaged ObjectをManaged Object Contextに挿入するには、NSManagedObject
でもNSManagedObjectContext
のクラスメソッドではなく、NSEntityDescription
のものを呼び出す必要がある。
それは、NSEntityDescription +insertNewObjectForEntityForName:inManagedObjectContext:
だ。
わかりにくい!
Core Dataのこのような分かりにくいAPIをラフにラップするオープンソースのライブラリが沢山存在している。
AppDelegate
の外でMainコンテキストとPrivateコンテキストを管理できるものや、クエリの生成を簡単にできるものなどなど。
Core Dataのアプリケーションを書くのには、多くのボイラープレート(初めに必要なコード)が必要だ。
これはだるい。
SSDataKitはこれを楽にする。
ある方法論を学んだら、それを別の技術にも適用しようというアイデアは何も驚くものではない。
Active Recordに詳しいRubyプログラマーがiOSアプリの開発に流入した事によって、それは起こった。
MagicalRecord
はRuby on RailsのActive Recordの取得方法にインスパイアされたもの。
このコードのゴールは、Core Data関連のコードをクリーンアップし、シンプルで、一行で取得できる、かつ最適化のためにNSFetchRequest
を変更できる余地を残す事。
ライトウェイトにActiveRecord的にCore Dataのオブジェクトを取り扱えるもの。
シンタックスはRuby on Railsに酷似している。
AppDelegateのコードはなし。
Kiwi
で完全にテストされたライブラリだ。
面白いことに、.Netから来た開発者も、同じように慣れ親しんだパラダイムをiOS開発でも行おうとする。
それは、LINQのパラダイムだ。
LINQはSQLライクだが、言語に統合されたものだ。
NSPredicate
やNSSortDescriptor
のようなキーバリューコーディングは、以下のようにいい感じの構文になる:
from c in SomeCollection
where c.SomeProperty < 10
select new {c.SomeProperty, c.OtherProperty};
ios-queryable supports LINQ-style query composition and deferred execution, and implements a subset of IEnumerable’s methods, including where, take, skip, orderBy, first/firstOrDefault, single/singleOrDefault, count, any, and all.
ReactiveCocoa は、Objective-CでFunctional Reactive Programmingのパラダイムを可能にするライブラリ。
それをCore Dataにも使ったものが存在する。
ReactiveCoreData (RCD)は、ReactiveCocoaの世界にCore Dataを持ち込もうとするもの。
ほとんどのiOSアプリはウェブサービスと通信する。
Core Dataを使うアプリにとって、RESTまたはRPCスタイルのウェブサービスからレコードを取得・更新・削除する事は共通だ。
ローカルのキャッシュとサーバ側との一貫性を保持するのは、トリッキーだ。
オブジェクトを常に最新の状態に保ち、重複を削除して、APIのエンドポイントとエンティティをマップし、衝突を調整し、ネットワーク到達性を管理する…これらは頑健なクラサバ型アプリの作成においてデベロッパが直面するいくつかの問題だ。
幸運な事に、これらの心配を軽減するライブラリが多く存在する。
RestKitは、RESTfulなウェブサービスとクライアントを連携させるためのiOSとMac OS Xで動作するモダンなObjective-Cフレームワークだ。
Core Dataとシームレスに統合するオブジェクトマッピングエンジンを提供し、AFNetworking
上に構築されたプリミティブなHTTP通信機能群を提供する。
エレガントで入念にデザインされたAPIによって、RESTfulのモデリングは魔法のように簡単になる。
AFIncrementalStoreはNSIncrementalStore
のサブクラスで、AFNetworking
を使ってプロパティとリレーションシップが必要な時に自動で取得してくれる。
MMRecordはブロックベースでシームレスにウェブサービスと統合できるiOSとMac OS Xで動作するライブラリ。
Core Dataモデルの構成を利用して、APIのレスポンスから自動的にオブジェクトグラフを作成する。
どのネットワークライブラリでも動作するようにできていて、シンプルな導入方法を提供する。
SLRESTfulCoreDataはAFNetworking
とSLCoreDataStack
上に構築されたもので、JSON REST APIとCore Dataモデルを数分で統合できる。
OvercoatはAFNetworking
の拡張で、デベロッパに簡単にMantleモデルオブジェクトが使えるようにする。
MantleはCocoaとCocoa Touchアプリケーションで簡単にモデルレイヤーを記述できるようにする。
アダプターはRESTなどの一般的な用途のインターフェースを通じて情報を同期するのに対して、シンクロナイザはもっと直接的なプロトコルを用いて、よりよい統合性とパフォーマンスを提供する。
MacとiPhone、iPhone同士、iPhoneとiPadなど、デバイス間でCore Dataを自動で同期する。
UbiquityStoreManagerはCore DataでiCloud統合を実装するコントローラ。
FireDataはシームレスにCore DataとFirebaseを統合する。
Mogeneratorを紹介しないで、Core Data系ライブラリを紹介しているとは言えないだろう。
MogeneratorはiPhone以前の時代から存在し続けている、Core Dataを使ったアプリケーションの開発において欠く事ができないツールだ。
Core Dataはここ数年で大きく変わったのに、Apple提供のツールは機能性に乏しいままだ。
でも幸運なことに、Wolf Rentzsch氏がカバーしてくれた。
Mogeneratorはコマンドラインツールで、.xcdatamodel
ファイルを渡すとエンティティごとに2つのクラスを生成する。
1つめのクラスは_MyEntity
で、マシン向けのもので継続的に上書きされ、データモデル設計と同じ状態に保たれる。
2つめのクラスはMyEntity
で、_MyEntity
のサブクラス。こっちはカスタムなロジックを記述するためのもので、生成以降は上書きされない。
いかがでしたでしょうか。
万能薬は存在しませんが、用途ごとに合ったものを使う事で劇的に開発効率は向上するでしょう。
複数種類のファイルを取り扱うようなアプリを思い浮かべてみて下さい。
対応するファイル形式を柔軟に増やせるようなアーキテクチャを、Objective-Cではどう構築するのが良いでしょう?
各形式を取り扱うモジュールがあって、それらは定型化された仕様に則って振る舞うような一般的なsubclassingモデルと、ファクトリパターンが良さそうです。
しかし、取り扱える種類が増えると、モジュールを統括する部分(ファクトリ部)の実装が肥大化する問題が発生します。
例えば、指定した拡張子に対応するクラスのインスタンスを返す関数とか。
更に、新しい形式を追加した時に、ファクトリ部への追加実装の手間も後々に負担となったり、実装漏れが生ずる可能性があります。
ファクトリ部をスッキリさせるには、通常のsubclassingモデルよりももう少し粗結合な実装方法を検討してみると解決するかもしれません!
それは、基底クラスのサブクラスの列挙部をハードコーディングするのではなく、ランタイムで列挙する方法です。
サブクラスに、ファクトリ部で取り扱いが必要な情報を提供するGetterメソッドやプロパティを持たせます。
これなら、新モジュールの登録忘れや一貫性を崩す心配を軽減できます!
NSObject
に対してメソッドを追加するカテゴリを紹介します。
追加されるメソッドの+ classNamesForSubclasses
を、あるクラスをレシーバにして呼び出すと、その子クラスの名前がNSArray
で返ります。
チョー簡単ですね!
ヘッダファイル(NSObject+AutomaticFactory.h
):
#!objectivec
#import <Foundation/Foundation.h>
@interface NSObject (AutomaticFactory)
+ (NSArray*) classNamesForSubclasses;
@end
ソースファイル(NSObject+AutomaticFactory.m
):
#!objectivec
#import "NSObject+AutomaticFactory.h"
#import <objc/runtime.h>
@implementation NSObject (AutomaticFactory)
+ (NSArray*) classNamesForSubclasses;
{
int numClasses = 0, newNumClasses = objc_getClassList(NULL, 0);
Class *classList = NULL;
while (numClasses < newNumClasses) {
numClasses = newNumClasses;
classList = (Class*)realloc(classList, sizeof(Class) * numClasses);
newNumClasses = objc_getClassList(classList, numClasses);
}
NSMutableArray *classesArray = [NSMutableArray array];
for (int i = 0; i < numClasses; i++) {
Class superClass = classList[i];
do {
// recursively walk the inheritance hierarchy
superClass = class_getSuperclass(superClass);
if (superClass == [self class]) {
[classesArray addObject:NSStringFromClass(classList[i])];
break;
}
} while (superClass);
}
free(classList);
return classesArray;
}
@end
プラグイン的な実装をしている場合は、検討してみてはいかがでしょうか?