[iOS] iOS5 から標準で UINavigationBar に複数のボタンを配置することができるようになった

2012年1月5日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

UINavigationItem の API に iOS5 から rightBarButtonItems があることに気がついた。複数形ということは...?

早速試してみた。こうすると。
UIBarButtonItem *item1 = [[UIBarButtonItem alloc]
                              initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
                              target:self
                              action:@selector(touched:)];
    
    UIBarButtonItem *item2 = [[UIBarButtonItem alloc]
                                initWithBarButtonSystemItem:UIBarButtonSystemItemCamera
                                target:self
                                action:@selector(touched:)];

    self.navigationBar.topItem.rightBarButtonItems =
        [NSArray arrayWithObjects:item1, item2, nil];
こうなる。
複数ボタンが標準でサポートされたのか。

横向きも問題なし。

スペースも入れられる。


3個もいける。


左も leftBarButtonItems が用意されている。

今回は試していないが戻りボタン(左のとんがっているやつ)がある場合はその右側に表示されるとのこと。

左右にボタンを配置するとタイトル→左→右の順で優先される。下記は左右に4つのボタンを指定した時の表示。幅が不足している場合は表示されない。

横向きにすると全部表示された。



タイトルが長いとその分表示幅が狭くなるので表示個数が減る。

なお右ボタンの場合、右から順番に配置される。


ソースコード


GitHub からどうぞ。
MultiNavigatorItemButtons at 2012-01-05 from xcatsan/iOS5-Sample - GitHub


関連情報


UINavigationBar に複数の UIBarButtonItem を配置するには - 24/7 twenty-four seven
UIToolbar をカスタムビューとして配置する方法。iOS 4 ではこういった方法しか無い。



リファレンスマニュアルを mac から ios に切り替える(割とどうでもいい)Tips

2012年1月3日火曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

Googleで Appleのサイトのリファレンスマニュアルを検索すると iOSではなく Mac OS X の方がヒットすることがある(特にNS系クラスなど)。これを iOSに切り替えるTips。

方法は簡単で URLの mac を ios へ変えて再読込するだけ。

こうなる↓

両方のOSに存在する実装であれば、クラスリファレンスに限らず各種ガイド・マニュアル類でも同じ方法が使える。

Cocoaの日々 - 2012年正月

2012年1月2日月曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

あけましておめでとうございます。
本年もよろしくお願いします。

毎年正月はこのブログのことについて書いています。今年も思ったことをとりとめなく書いておきます。

昨年はブログの毎日更新をやめた他、秋以降は忙しかったこともありブログの更新頻度はずいぶん下がってしまいました。今年も当面は頻度が下がると思いますが技術情報を少しでも提供して共有できればと思っています。

また昨年正月に目標としていたことはほとんど実行できませんでした。
Cocoaの日々: Cocoaの日々 - 2011年元旦
唯一できたのは「Cocoaの日々情報局」を立ち上げたくらい(RoRは使っていないが)。

その点プログラミングに関して昨年は不本意な一年でした。ただその分、子育てやハーフマラソン完走、TOEIC目標クリアなどそれなりに充実した一年だったと思います(なかなか両立は難しい...)。

さて今年は趣味のプログラミングに関して今までのやり方を大きく変えようと考えています。

(今まで)
・基本的にライブラリを使わず手作り
・知らない技術は網羅的に検証しながら進める
・その成果を基本的にブログで公開
・1つのアプリに時間をかける

これを今年は変えていく。

(今年)
→ 他の人のライブラリを積極的に利用する
→ 丁寧な検証はやらない
→ ブログは最小限に
→ 1つのアプリに時間をかけない

趣味なので時間をかけて検証して石を彫るように進める開発はそれなりに楽しかったけれど、同じやり方を続けるのは進歩がない。それに以前と違って使える時間も無い。そこで今年は思い切ってそれを変えていく。うまくいくかわからないが良い変化になればと考えている。

この数ヶ月は昨年来開発を続けてきたiPhoneアプリを完成させて公開することがまずは今年最初の目標になります(Evernote系のアプリを製作中)。その後は2〜3ヶ月毎に1本づつアプリを作って行きたい。

- - - -

情報局ともどもこのブログを今年もよろしくお願いします。



[iOS] AVFoundation のカメラでフォーカスと露出をタッチで合わせる

2011年12月2日金曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

AVFoundation を使い、タッチでフォーカスと露出を決められるカスタムカメラを作る。今日の主題はタッチフォーカス&露出なのでプレビューを表示するだけで撮影(画像の保存)は実装していない。

サンプル


まずはサンプルから。起動すると真ん中に四角が表示される。

この状態で任意の場所をタッチするとそこにフォーカスと露出が合う。

手前を合わせてみた。


実装 - プレビュー


カメラ入力をプレビュー表示する部分の説明は今回割愛する。この辺りは下記のドキュメントが詳しい。ひと通り読めば簡単に実装できる。

AV Foundation プログラミングガイド

もしくは



など。後者の本は iOS4 となっているが iOS5 でも十分に役立つ情報が掲載されている。おすすめの本。


実装 - フォーカスと露出


任意の点にフォーカスと露出をあわせるプロパティが用意されている。
AVCaptureDevice.h

@property(nonatomic) CGPoint focusPointOfInterest;
@property(nonatomic) CGPoint exposurePointOfInterest;
基本的にはここにフォーカスもしくは露出を合わせたい座標を入れればいい。

ただしこのプロパティに設定する値は次のルールに従う必要がある。

(1) 0.0〜1.0 に正規化した値
(2) ランドスケープ(横向き/ホームボタン右)の時の左上を原点とする座標系

「AVFoundation プログラミングガイド(PDF)」によれば次のように解説されている。
ホームボタンが右側になる横長モードでは、{0,0}が画像領域の左上を表し、{1,1}が右下を表します。これ
は、デバイスが縦長モードであっても同じです。


つまり通常のポートレイト(縦向き/ホームボタン下)の状態の時に画面上のタッチ位置をこれらに反映させるには、(1)の正規化と(2)の座標系への変換が必要になる。

(1)の正規化は単純に大きさで位置座標を割ってやれば良い。 (x/width, y/height)

ポートレイトの座標系(左上が原点)を使っている時のそれぞれの座標系の関係はこんな感じ。

x と y を入れ替えて、かつ y軸の方向に反転してやればいい。これは(1)の正規化が済んでいれば簡単にできる。

サンプルでのコードはこんな感じ。
- (void)setPoint:(CGPoint)p
{
    CGSize viewSize = self.view.bounds.size;
    CGPoint pointOfInterest = CGPointMake(p.y / viewSize.height,
                                          1.0 - p.x / viewSize.width);

フォーカスの場合は、この値を focusPointOfInterest へ渡し、focusMode を設定すれば良い。こんな感じ。
if ([videoCaptureDevice isFocusPointOfInterestSupported] &&
            [videoCaptureDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
            videoCaptureDevice.focusPointOfInterest = pointOfInterest;
            videoCaptureDevice.focusMode = AVCaptureFocusModeAutoFocus;
        }

露出の方は、exposurePointOfInterest 渡すだけでは駄目で、もう少し手間が必要となる。
if ([videoCaptureDevice isExposurePointOfInterestSupported] &&
            [videoCaptureDevice isExposureModeSupported:
                  AVCaptureExposureModeContinuousAutoExposure]){
            self.adjustingExposure = YES;
            videoCaptureDevice.exposurePointOfInterest = pointOfInterest;
            videoCaptureDevice.exposureMode =
                  AVCaptureExposureModeContinuousAutoExposure;
        }
ここまではフォーカスとほぼ同じ。これに加えて露出の場合は、exposurePointOfInterest設定後に AVCaptureDevice の adjustingExposure プロパティを監視しこの値が NO(つまり露出合わせが終了)になったタイミングで exposureMode を AVCaptureExposureModeLocked にする必要がある。

- (void)viewDidLoad
{
   :
            [videoCaptureDevice addObserver:self
                                 forKeyPath:@"adjustingExposure"
                                    options:NSKeyValueObservingOptionNew
                                    context:nil];
   :
監視を設定しておき値が変化したら処理をする。
- (void)observeValueForKeyPath:(NSString *)keyPath
  ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (!self.adjustingExposure) {
        return;
    }
    
 if ([keyPath isEqual:@"adjustingExposure"]) {
  if ([[change objectForKey:NSKeyValueChangeNewKey] boolValue] == NO) {
            self.adjustingExposure = NO;
            AVCaptureDevice* videoCaptureDevice =
            [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
            
   NSError *error = nil;
   if ([videoCaptureDevice lockForConfiguration:&error]) {
     [videoCaptureDevice setExposureMode:AVCaptureExposureModeLocked];
    [videoCaptureDevice unlockForConfiguration];
   }
  }
 }
}

試してみよう。まずは右にある MacBook Pro の明るい部分に合わせた。

次に手前の暗い 3GS。

うまくいったようだ。


ソースコード


GitHub からどうぞ。
CameraSample at 2011-12-02 from xcatsan/iOS-Sample-Code - GitHub


参考情報


iPhone4でサポートされてない露出モードのエラーが出たけど - Debian GNU/Linux 3.1 on PowerMac G4

露出の位置指定はここの情報が参考になった(紹介されているコードは若干不備がある 2011-12-03追記:記事著者の方が修正してくれました。素早い!)。また毎回値監視をつけたり外したりするのは管理しずらいのでサンプルでは viewDidLoad で監視を開始している(監視外しは今見たら入れ忘れてた→dealloc, viewidiUnloadなどに入れておく)。


github で Forkしてみる

2011年11月25日金曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

github にはソースを自分用にカスタマイズできる Fork という機能があるらしい。試してみた。

最初に github に自分のアカウントでログインしておきForkしたいソースのページを開く。そして右上の "Fork" ボタンを押す。

これだけ。自分のリポジトリに Forkされたリポジトリが作成される。

一旦、Fork したものは自分ですきなようにできる。例では MTStatusBarOverlay というライブラリを Fork してみた。

このライブラリにはサンプルアプリが付いていなかったので自分で作ってみる。Forkした先ほどのリポジトリを Clone して手元の PCへ持ってくる。

(参考)

Xcode でプロジェクトを開き、新しいターゲットを追加する。


簡単な動作確認なので Single View Application を使う。
ターゲットが追加された。

スキーマも一緒に作ってくれるのですぐにビルドできる。

アプリを動作させる為に必要なファイル一式も作成されている。

適当にコードを書いて動作確認が終わったらコミットする。GitHub.app で cloneしたならコミットもここでできる。
コミットが終わった。続いて github と同期を取る(git push する)。

完了。


github サイトで確認。でてる。

一旦 Fork してしまえば元のソースを気にせずカスタマイズができる。検証目的でいろいろコードを修正したい場合も便利。


[Mac] Lion から導入された XPC Services

2011年11月24日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

Mac OS X 10.7 から XPC Services という仕組みが導入された。

リファレンスによれば XPC Services は単一のアプリケーション専用に利用できる軽量なヘルパーツール(lightweight helper tools)と定義されている。アプリのバンドル内に組み込んで実行時に利用するのでこの点を見れば通常のライブラリと似ている。ライブラリと大きく異なるのは、XPC Services はアプリとは独立して動作していて、XPC Services がクラッシュしてもアプリに影響を与えない点。XPC Services は launchd管理下にあり、起動・停止の他、クラッシュした場合の再起動まで面倒見てくれる。こう見ると XPC Services はOS上のプロセスに近い(プロセスなのかまでは調べきれなかったがプロセス間通信と説明されているのでそうなんだと思う。Mac OS X で何か軽量なプロセスが用意されているのだろうか。)。

アプリが XPC Services を利用する場合は XPC Services API を利用する。このAPIは GCDをサポートしている。


XPC Services を使う用途として次の2点が挙げられている。
  1. 安定性の向上 〜 XPC Services が落ちてもアプリには影響を与えない。
  2. セキュリティの向上 〜 XPC Services毎にアクセス制御を細かく設定できて、アクセス可能な範囲を本体のアプリとは分離できる。Sandboxでの利用が想定されている。

Xcode4.2では XPC作成用のテンプレートが用意されている。
XPCを利用するには XPCをテンプレートから作成し、アプリに組み込めば良い。

以下はテンプレートから生成されたコード。
static void TestService_peer_event_handler(xpc_connection_t peer, xpc_object_t event) 
{
 xpc_type_t type = xpc_get_type(event);
 if (type == XPC_TYPE_ERROR) {
  if (event == XPC_ERROR_CONNECTION_INVALID) {
   // The client process on the other end of the connection has either
   // crashed or cancelled the connection. After receiving this error,
   // the connection is in an invalid state, and you do not need to
   // call xpc_connection_cancel(). Just tear down any associated state
   // here.
  } else if (event == XPC_ERROR_TERMINATION_IMMINENT) {
   // Handle per-connection termination cleanup.
  }
 } else {
  assert(type == XPC_TYPE_DICTIONARY);
  // Handle the message.
 }
}

static void TestService_event_handler(xpc_connection_t peer) 
{
 // By defaults, new connections will target the default dispatch
 // concurrent queue.
 xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
  TestService_peer_event_handler(peer, event);
 });
 
 // This will tell the connection to begin listening for events. If you
 // have some other initialization that must be done asynchronously, then
 // you can defer this call until after that initialization is done.
 xpc_connection_resume(peer);
}

int main(int argc, const char *argv[])
{
 xpc_main(TestService_event_handler);
 return 0;
一種のサーバとして動作するのでイベントが来たときの処理を書いていく。


アプリは XPC Services のconnection系 APIを使い、アプリと XPC間で通信を行う。以下は connection.h で定義されている関数。
xpc_connection_cancel
xpc_connection_create
xpc_connection_get_asid
xpc_connection_get_context
xpc_connection_get_egid
xpc_connection_get_euid
xpc_connection_get_name
xpc_connection_get_pid
xpc_connection_resume
xpc_connection_send_message
xpc_connection_send_message_with_reply
xpc_connection_send_message_with_reply_sync
xpc_connection_set_context
xpc_connection_set_event_handler
xpc_connection_set_finalizer_f
xpc_connection_set_target_queue
xpc_connection_suspend


参考情報


Mac OS X Technology Overview: Kernel and Device Drivers Layer
XPCの紹介


Daemons and Services Programming Guide: Designing Daemons and Services

XPCの概要


Daemons and Services Programming Guide: Creating XPC Services
XPC Services の利用説明


API Reference: XPC Services API Reference


App Sandbox Design Guide: App Sandbox in Depth
Sandbox での XPCの利用について。


- - - -
単一アプリ専用のプロセスを動かして利用するというアイディアは面白い。Sandbox での安全性を高めるのが目的と思われるが、うまく使えば再利用性の高い簡易サーバプロセスとして利用できそう。


新サイト「Cocoaの日々情報局」を開設しました

2011年11月21日月曜日 | Published in | 2 コメント

このエントリーをはてなブックマークに追加

サイトを新設しました。



最近このブログでiOSの開発情報提供を積極的にやってきましたが今後は「Cocoaの日々情報局」にその役割を移します。このブログ「Cocoaの日々」は前までのスタイル(開発日誌、検証情報や自作ライブラリの紹介など)に戻ります。

興味があれば新しいサイトをのぞいてみて下さい。
今後もよろしくお願いします。


人気の投稿(過去 30日間)