ネットワークの接続状態を取得する方法

ASIHttpRequest が Reachability を利用していたので、存在は知っていたが ARC 版が無くて困ったので、メモ。

Reachability の ARC 対応版を公開している人がいるみたい。
あと、Reachability で通信状態を取得するという使い方は知っていたが、通信状態が変化した際にコールバックさせることもできるみたいなので、メモしておく。

何だかんだで、自分でも ARC のコード書くようになっちゃったなぁ~。あと、blocks とかも見なくちゃいけなしぃ~。GCD とかも見てる。私は特に必要がなければ、 NSOperation がいいなぁ~。(^^)

・参考サイト: TORQUES LABS Reachability:iOSでネット接続を確認する公式ライブラリ
・ソース公開: Reachability (iOS) ARCified — Gist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 通信状態が変化した際に通知されるように設定する
- (void)reachabilityStart
{
    curReachability_ = [Reachability reachabilityForInternetConnection];
    [curReachability_ startNotifier];
 
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reachabilityChanged:)
                                                 name:kReachabilityChangedNotification
                                               object:nil];
}
 
- (void)reachabilityStop
{
    [curReachability_ stopNotifier];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"kReachabilityChangedNotification" object:nil];
}
 
// ネットワーク接続の状態が変化した際の処理
- (void)reachabilityChanged:(NSNotification*)note
{
    Reachability* curReach = [note object];
    NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
 
    NetworkStatus netStatus = [curReach currentReachabilityStatus];
    if (netStatus != NotReachable) {
        // 通信が再確保された際の処理
    }
}

大きな整数値を扱える long long int 型

iPhoneでの long long int 型のサイズは 8byte = 64bit

LLONG_MAX 7fffffffffffffff(9223372036854775807)
ULLONG_MAX ffffffffffffffff(18446744073709551615)

18446 74407 37095 51615(20桁)
とりあえず、桁あふれは気にしなくて良いかな? (^^)

参考: 大きな整数の取り扱い

xcode4 (4.4.1) ショートカット

久しぶりに xcode 触ったらヘッダとソースの表示切り替えができなくて焦った。(^_^;
というわけで、普段自分が使うショートカットをメモ。
ヘッダとソースの表示切り替えは、前の xcode から変更されているような気がするなぁ~

ビルド Cmd + b
プログラム起動 Cmd + r
プログラム停止からの継続 Control + Cmd + y
ヘッダ、ソースの切り換え(.h .m) Control + Cmd + ↑
ファイル ナビゲータを表示する Cmd + 1
検索ナビゲータ Cmd + 3
問題ナビゲータ(エラー) Cmd + 4
デバッグ ナビゲータ Cmd + 5
ブレイクポイント Cmd + 6
ファイル内検索 Cmd + f
プロジェクト内検索 Cmd + Shift + f
定義へジャンプ Cmd + クリック
戻る、進む Control + Cmd + ← / →
選択行をコメント Cmd + /
Undo Cmd + z
インデント戻す(右へシフト) Cmd + [
インデントする(左へシフト) Cmd + ]
指定行へジャンプ Cmd + l
フォーカス切り替え Cmd + j
デバッグ エリアの表示、非表示 Cmd + Shift + y
変数名を一度に変更する Control + Cmd + e
表示しているコードをプロジェクトナビゲータで選択表示 Shift + Cmd + j

Git について

git についてよく分かっていなかったので、調べてみた。
よく分からなかった原因は、git 特有の概念、用語などにあったと感じていたので、以下にまとめた。

概念については以下の資料を参照するのがいい。

git – 簡単ガイド 猫でもわかるGit 最初の一歩
Git – Book

用語についても、以下にまとめた。
origin, master, head とかよく意味がわかんなかったけど、少しすっきりした。

リポジトリからクローンして、コミットするまでのコマンドについてもまとめたので、
あとは実際の経験からの得られる知識を蓄積していけば OK でしょう。
改めて、ブランチって便利だなと感じたので、積極的に使っていきたい。^_^

インストール

macport でインストールする場合

$ sudo port install git-core +gitweb +svn

設定について

~/.gitconfig
特定のユーザーに対する設定値を保持する。
–global オプションを指定することで、明確にこのファイルの読み書きを行う。

/etc/gitconfig
システム上の全てのユーザーと全てのリポジトリに対する設定値を保持する。
–system オプションを git config に指定すると、明確にこのファイルに読み書きを行う。

現在使っている、あらゆるリポジトリの Gitディレクトリ設定ファイル ( .git/config )
特定の単一リポジトリに対する設定値を保持する。
それぞれのレベル値は以前のレベル値を上書きするため、.git/config 中の設定値は /etc/gitconfig の設定値に優先される。

.gitignore
無視させたいファイルのパターンを保持したファイル。
.gitignore ファイルに記述するパターン規則は、以下の通り。

空行あるいは # で始まる行は無視される
標準の glob パターンを使用可能
ディレクトリを指定するには、パターンの最後にスラッシュ (/) をつける
パターンを逆転させるには、最初に感嘆符 (!) をつける

1
2
3
4
5
6
# コメント行
*.a       	# .a ファイルは管理対象外とする
!lib.a    	# しかし、lib.a ファイルだけは .a であっても追跡対象とする
/TODO           # ルートディレクトリの TODO ファイルだけを対象外とし、サブディレクトリの TODO は対象外としない
build/    	# build/ ディレクトリのすべてのファイルを対象外とする
doc/*.txt 	# doc/notes.txt は無視しますが、doc/server/arch.txt は無視しません

xcode 用の gitignore

1
2
3
4
5
6
7
8
9
10
11
12
.DS_Store
*.swp
*~.nib
build/
 
*.pbxuser
*.perspective
*.perspectivev3
 
#!xcuserdata/
#*.xcuserstate
UserInterfaceState.xcuserstate

用語について

リポジトリをクローンする
Git リポジトリをコピーすること。
Subversion などの checkout と意味が違うことに注意。
Git は、サーバーが保持しているデータをほぼすべてコピーする。
そのプロジェクトのすべてのファイルの全履歴が、git clone で取得することができる。

リポジトリをクローンするには git clone [url] とする。
例えば、Ruby の Git ライブラリである Grit をクローンする場合は以下のようにコマンド入力する。

$ git clone git://github.com/schacon/grit.git

ステージング・エリア
Gitディレクトリに含まれる、次のコミットに何が含まれるかという情報。

origin サーバー
クローン元のサーバーに対して Git がデフォルトでつける名前。

master ブランチ
クローンした地点でこのブランチ名とサーバー名が自動設定される。

HEAD ポインタ
作業中のブランチを指し示す特別なポインタ。
Git では、HEAD は作業しているローカルブランチへのポインタとなる。

git clone
git clone コマンドはローカルの master ブランチが、(取得元サーバーの) リモートの master ブランチを追跡するよう自動設定する。
リモートに master ブランチが存在することを前提としている。

git pull
通常は最初にクローンしたサーバーからデータを取得し、現在作業中のコードへのマージを試みる。

リベース
一方のブランチにコミットされたすべての変更をもう一方のブランチで再現する。

コマンド入力について

設定を確認する方法
$ git config –list

変更を確認する方法
$ git status
$ git diff
$ git diff –staged

git で管理するファイルをコミットする

1
2
3
$ git init					# 既存ディレクトリでのリポジトリの初期化
$ git add *.c					# 管理するファイルを追加する
$ git commit –m 'initial project version'	# コミットする

ステージングエリアの準備ができたら、変更内容をコミットすることができる。
コミットの対象となるのはステージされたものだけ、つまり追加したり変更したりしただけで
git add を実行していないファイルはコミットされないことに注意。

$ git commit -a -m '...'
$ git pull origin master マスタの改変を取り込む
$ git branch 現在のブランチを確認する
$ git checkout (ブランチ名) ブランチを切り換える
$ git status コミット残があるか判断する
$ git add (ファイル名) ファイルを追加する
$ git merge (ブランチ名) ブランチをマージする
$ git push origin master originサーバのmasterブランチへpushする

ファイルを削除、変更する方法

$ git rm ファイル名 ファイルの削除がステージされる
$ git rm -f ファイル名 ステージされているファイルを削除する
$ git rm –cached ファイル名 ファイルをステージから削除するのみ
$ git mv file_from file_to ファイル名を変更する (ステージから削除し、新しいファイル名でステージしてくれる)

直近のコミットを修正する方法

$ git commit –amend 直近のコミットを変更

直近のコミットを修正するには以下の様にコマンドを入力する。

1
2
3
$ git commit -m '初期コミット'
$ git add 忘れてたファイル
$ git commit --amend

ログを参照する方法

$ git log ログの閲覧
$ git log –p -2 -p で各コミットの diff を表示し、-2 で直近の 2 エントリだけを出力する
$ git log –pretty=format:”%s” –graph ログをグラフィカルに出力する
$ git log –oneline ログを1行ずつ出力する

タグをつける方法

$ git tag タグの一覧表示
$ git tag -a v1.4 -m ‘my version 1.4’ 注釈付きのタグを指定する
$ git show v1.4 タグの参照

ブランチを操作する方法

$ git checkout testing ブランチを testing へ切り換える
$ git checkout -b iss53 ブランチ iss53 を作成して、切り換える
$ git checkout master ブランチを master へ切り換える
$ git merge hotfix ブランチをマージする
$ git branch -d hotfix ブランチを削除する

submodule を更新する方法

$ git submodule foreach ‘git checkout master; git pull’ すべてのサブモジュールを更新する

Command Line Tools のインストール方法

xcode 4.3 以降は Command Line Tools がインストールされない。
そのため、別途インストールする必要がある。

インストールするには以下の方法がある。

1. Apple Developer サイトから入手する
https://developer.apple.com/downloads/index.action

2. Xcode の [Preferences…]-[Downloads]からインストールする

xcode でタグジャンプができない場合の対処

xcode でコーディングしていると何かの拍子にタグジャンプができなくなることがありました。
タグのインデックスを再生成する方法が分からなかったのですが、以下の操作でタグの再生成ができるようです。
(シンタックス カラー表示が正常に行われない場合にも有効みたい)

  1. Organizer を起動する
  2. Projects を選択する
  3. [Derived Data] の [Delete…]ボタンを押下する
  4. プロジェクトをクリーン、ビルドする

xcode4 のテキスト編集を vim ライクにしてくれるプラグイン

JugglerShu / XVim
https://github.com/JugglerShu/XVim

ここ数日 xcode にこのプラグインをインストールして xcode + vim キーバインディングで作業しています。
とても便利です。
アンインストールも↓で OK みたいです。
開発が活発なようなので、毎日チェックしてます。

– Uninstall
Delete the following directory:
$HOME/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins/XVim.xcplugin

条件に合致する文字のみ取得する方法

テキストフィールドなどから入力された文字列より、条件に合致する文字を取得する場合に正規表現を使えれば便利だなぁ~と調べるとやはりありました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 入力された文字列から"全角ひらがな"、"全角カタカナ"のみ取得する
- (NSString *)getHiraganaKatakana:(NSString *)inString
{   
    if ([inString length] == 0) {
        return @"";
    }
 
    // 正規表現オブジェクトを作成する
    NSRegularExpression *regexp;
    NSError *error = nil;
    regexp = [NSRegularExpression regularExpressionWithPattern:@"[ぁ-んァ-ン]" options:0 error:&error];
    if (error != nil) {
        NSLog(@"%@", error);
        return @"";
    }
 
    NSArray *checkingResultArray = [regexp matchesInString:inString options:0 range:NSMakeRange(0, inString.length)];
 
    NSMutableString *outString = [NSMutableString string];
 
    for (NSUInteger i = 0; i < [checkingResultArray count]; i++) {
        NSTextCheckingResult *checkingResult = [checkingResultArray objectAtIndex: i];
        if (checkingResult) {
            [outString appendString:[inString substringWithRange:[checkingResult rangeAtIndex:0]]];
        }
    }
 
    return outString;
}

入力された文字が数値か判断する方法

入力された文字が数値かどうか?判定する処理はいろいろありますが、cocoa の流儀ではどうするのかと調べると NSScanner ってのが使えると知りました。
初めて使いましたが、便利ですね。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 数値入力として妥当か判断する
- (BOOL)isDigit:(NSString *)inString
{
    if ([inString length] == 0) {
        return NO;
    }
 
    NSCharacterSet *digitCharSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
 
    NSScanner *aScanner = [NSScanner localizedScannerWithString:inString];
    [aScanner setCharactersToBeSkipped:nil];
 
    [aScanner scanCharactersFromSet:digitCharSet intoString:NULL];
    return [aScanner isAtEnd];
}

参考リンク:
terrazzoの日記 ■[Cocoa]Re: NSString が整数値かどうか調べる関数

Apple Push Notification サービス(APNs) の実装方法

プッシュ通知の理解には、以下のドキュメントは、以下のものが参考になる
Local NotificationおよびPush Notificationプログラミングガイド

実装については、以下の公開されているコードが参考になる
・ApnsPHP: Apple Push Notification & Feedback Provider
http://code.google.com/p/apns-php/

・EASY APNS
APPLE PUSH NOTIFICATION SERVICE USING PHP & MYSQL
http://www.easyapns.com/
サーバ(PHP)、クライアント(Objective-C) のコードが同梱されている
また、HP には実装の手順が動画で公開されている(約10分)

今回 検証には、ApnsPHP を使用した。
(EASY APNS は mysqli を使用しているが、私の検証用レンタルサーバで動かなかったため。(T_T))

プッシュ通知を実装するには、以下の作業が必要となる

1. プッシュ通知に対応したプロビジョニングプロファイルの作成とインストール

– iOS Provisioning Portal から “Push Notifications”に対応した”App IDs”を取得する
– App IDs を指定したプロビジョニング ファイルを取得する
– 開発環境、デバイスにインストールする

プッシュ通知には、プッシュ通知に適応したプロビジョニング ファイルを使用する必要がある。
既に作成しているプロビジョニング ファイルにプッシュ通知 属性を付加することができなかったため、
新たにプッシュ通知に適応した “App IDs” を作成し、その ID を指定したプロビジョニング ファイルを取得した。

2. デバイストークンを取得する

デバイストークンとは、iOS デバイスが Remote Notification を受信するために、APNS へデバイス登録を行った際に取得できるID。
(サービス提供者が iOS デバイスへ APNS を介してメッセージ通知する際に利用される)

以下のサンプルでは、iOS アプリ起動時に Remote Notification 受信するためにデバイスを登録し、APNS からデバイス トークンを受信している。
(ログにデバイス トークンが出力されるので、PHPスクリプトに適用して利用する)

アプリ起動時などでデバイスを APNS へ登録する

1
2
3
4
5
6
7
// アプリケーションが起動した際の処理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Remote Notification を受信するためにデバイスを登録する
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge
                                                                           | UIRemoteNotificationTypeSound
                                                                           | UIRemoteNotificationTypeAlert)];

APNS から返されるデバイストークンに付加されている文字をカットする

1
2
3
4
5
6
7
// デバイストークンを受信した際の処理
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
 
    NSString *deviceToken = [[[[devToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""] 
                                                      stringByReplacingOccurrencesOfString:@">" withString:@""] 
                                                      stringByReplacingOccurrencesOfString: @" " withString: @""];
    NSLog(@"deviceToken: %@", deviceToken);

プッシュ通知は、NSDictionary で渡される

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// プッシュ通知を受信した際の処理
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
#if !TARGET_IPHONE_SIMULATOR
    NSLog(@"remote notification: %@",[userInfo description]);
    NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];
 
    NSString *alert = [apsInfo objectForKey:@"alert"];
    NSLog(@"Received Push Alert: %@", alert);
 
    NSString *sound = [apsInfo objectForKey:@"sound"];
    NSLog(@"Received Push Sound: %@", sound);
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
 
    NSString *badge = [apsInfo objectForKey:@"badge"];
    NSLog(@"Received Push Badge: %@", badge);
    application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue];
#endif
}

3. SSL Distribution証明書、秘密暗号鍵の取得とサーバへの配置

SSL Distribution証明書と秘密暗号鍵を、APNsに接続するサーバにインストールする必要がある。

私は以下の手順で証明書、秘密暗号鍵を作成しました。
ネット上にはいくつかの手順が紹介されていますが、以下の資料が一番わかりやすかったです。
結果、以下のファイルが作成できれば OK。

・server_certificates_bundle_sandbox.pem
・entrust_root_certification_authority.pem

How to generate a Push Notification certificate and download the Entrust Root Authority certificate

http://code.google.com/p/apns-php/wiki/CertificateCreation

・CertificateCreation
How to create a Push Notification certificate in iPhone Developer Program Portal

・Generate a Push Certificate
Push Notification のセキュリティ認証情報の取得

・Verify peer using Entrust Root Certification Authority
Download the Entrust Root Authority certificate directly from Entrust Inc. website:

4. PHPサーバ スクリプトの対応

最後に、iPhone へプッシュ通知するコードを用意します。
ApnsPHP の sample_push.php (プッシュ通知用)にデバイス トークンを指定すれば OKです。
また、APNS と通信するので、以下の証明書を配置しておきます。

– server_certificates_bundle_sandbox.pem
– entrust_root_certification_authority.pem

ここまで作業すれば、無事、プッシュ通知できるはずです。
お疲れ様でした。^_^

もし、PHP スクリプトがエラー出力するようであれば、以下の点をチェックしてみてください。
では!

注意:
ApnsPHP (at revision 100) – ApnsPHP-r100.zip に含められている sample_push.php は、
以下のファイル名の綴りが間違っているようです。
私はこれで2分くらい悩みました。。。(T_T)
2分で済んで助かりましたが、運が悪いともっと悩んでいたはず。
恐ろしい罠ですね。

1
2
3
4
5
6
// Instanciate a new ApnsPHP_Push object
$push = new ApnsPHP_Push(
	ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,
//	'server_cerificates_bundle_sandbox.pem'		// 綴りが間違ってる
  'server_certificates_bundle_sandbox.pem'
);