MOSADeN ONLINE 第24回の記事を入稿しました。今回は、iOSでキャプチャしている映像の中で変化があったときに、それを知るための方法についてです。27日にMOSA会員限定で公開されます。iOS 5.0ではこんなに簡単に検出できるのかと私自身は驚愕しました。
http://www.mosa.gr.jp/mosaden/
▲ページトップへ戻るMOSADeN ONLINE 第24回の記事を入稿しました。今回は、iOSでキャプチャしている映像の中で変化があったときに、それを知るための方法についてです。27日にMOSA会員限定で公開されます。iOS 5.0ではこんなに簡単に検出できるのかと私自身は驚愕しました。
http://www.mosa.gr.jp/mosaden/
▲ページトップへ戻るアドレスブックをiCloudと統合したときに、iCloudに統合されたデータのバックアップもかねて、iCloudに保存されない、ローカルのMac内に保存されたデータを明確にしたいと思い、その方法を探してみました。
以前であれば、アドレスブックのグループ一覧が表示される領域に、「このMac内」と「iCloud」というように分かれていたはずなのですが、新しいMacをセットアップしてみるとそれが見当たらず、iCloudと統合後はすべてiCloudに保存されるようになっていました。
探してみると、次のようにすれば表示されることがわかりました。
お知らせです。MOSADeN Onlineの第23回の記事をアップしました。16時にMOSA会員限定で公開になります。今回は、iOSデバイスから外部ディスプレイを使用する方法についてです。iOS 5ではミラーリングだけではなく、アプリから独自のビューコントローラを外部ディスプレイに表示することもでき、Apple TVを使えばAir Play越しもできます。
▲ページトップへ戻るI had received the question about the forward class declaration of the Objective-C and this is the answer.
If you want to declare the forward class declaration, you can write following:
The member variable of the Objective-C class needs the class name is declared before the variable is appeared. In this case, you can write the “#import” in the header file and read the declarations. For example, this code:
This code could be error when you write the following code in the “MyObject.h” file.
Following errors will be occurred when you complie abobe code.
The meaning of these errors are:
Why the complier says the declration is not appeared? The declration is imported with “#import”.
You can know the reason by thinking how the preprocessor works. The preprocessor does following.
“MyObject.h” file
“MyObjectB.h” file
To avoid this problem, you can use the “@class”. Above code can be written following.
“MyObject.h” file
“MyObjectB.h” file
There is the foward protocol declration:
Either you write the protocol declation before or after the class declation, the compiler reports error. You can avoid this problem by using the foward protocol declaration.
The sample code is available.
▲ページトップへ戻るクラス名の前方宣言について質問をもらったので少しまとめます。
Objective-Cでクラス名を前方宣言したいときには「@class」文を使用します。例えば「MyObject」という名前のクラスであれば、次のように書きます。
ヘッダファイルの中で、Objective-Cのクラスのインスタンスをメンバー変数にしたいときはクラスが存在することを知らなければいけません。このようなときに「#import」文をヘッダファイルに書いてクラスの宣言を読み込みます。例えば次のようなコードです。(このヘッダファイルを「MyObjectB.h」ファイルとします)
このとき、もしも「MyObject.h」ファイルに次のようなコードが書かれていると問題が起こります。
このコードをビルドしようとすると、コンパイラは次のようなエラーを表示します。
エラーメッセージの意味は次の2つです。
「#import」文で、それぞれのクラスのインターフェイスを読み込んでいるのになぜ「定義が無い」といわれてしまうのでしょうか?
実は、ビルドのときにプリプロセッサによってどのような処理が行われているかを考えてみると原因が分かります。プリプロセッサはビルドするときに「#import」文などを実行して、次のような動きをします。(「Cocoa/Cocoa.h」ファイルはここでは関係ないので、その内容は割愛します)
「MyObject.h」ファイルの処理(「MyObject.m」ファイルのコンパイル)
「MyObjectB.h」ファイルの処理(「MyObjectB.m」ファイルのコンパイル)
このような、循環インクルード(循環インポート)における問題を防止するために使用するのが「@class」文です。上記の2つのコードを次のように修正します。
「MyObject.h」ファイル
「MyObjectB.h」ファイル
このようにすると、お互いのヘッダファイルを参照しないので、循環する恐れが無く、クラスが存在することがわかっているのでメンバー変数も定義できます。
同じようにプロトコルも前方宣言ができます。次のようなコードです。
デリゲートメソッドをプロトコルで定義したときなど、クラスを先に書くか、プロトコルを先に書くかのどちらを行ってもお互いを知らないからエラーになるのを防止できます。
ただし、一つ注意。前方宣言では名前のみなので、インスタンスを確保する(「alloc」メソッドを呼ぶとき)とか、クラスを継承するとかのときには使えません。サブクラスを定義するときには必ず親クラスの定義が必要です。ですので、ヘッダファイルでは親クラスのヘッダファイルの読み込みは必須です。
それと、前方宣言することでのメリットは循環インクルード(循環インポート)の防止だけではなくコンパイル時間の削減にも効果あります。ヘッダファイルが大量のヘッダファイルをインポートしていて、インポートされているヘッダファイルも別のヘッダファイルを…などとなっていくると、ビルド時間が長くなっていきます。前方宣言ならそのようなことが起きないので、ビルド時間が指数関数的に増えるということはなくなります。もちろん、インクルードではなく、そもそものコードが膨大な場合にはビルド時間がかかるというのはかわりません。また、ヘッダファイルに依存関係が凄まじいと1つファイルを変更すると全体フルビルドみたいな状況になるので、できるだけヘッダファイルの依存関係を減らしておくというのは精神衛生上もよいことだと思います。
検証に使ったプロジェクトファイル(上記のコードが書いてあるだけですが)はこちらからダウンロードできます。ビルドできる状態のコードになっているので、「#import」文のコメントアウトを解除して、「@class」文をコメントアウトしてからビルドしてみてください。エラーになります。(Mac OS X 10.6 + Xcode 3.2.6で確認しました)
サンプルコードのダウンロード
▲ページトップへ戻るMOSADeN ONLINE 第22回の記事をアップしました。11月24日の朝9時にMOSA会員向けに公開されます。今回はTwitterフレームワークの続きで、Twitterフレームワークを使ってTwitter APIを呼ぶ方法についての紹介です。システムに設定されたアカウント情報を使って認証して、ユーザーのタイムラインを取得します。
▲ページトップへ戻るTransmitをインストールしようと思ったのですが、どうしても、Mac App Storeでは「インストール済み」という認識になってしまい、再インストールができないという症状になっていました。他のマシンでは問題ないし、アプリケーションフォルダからは削除済みなのになぜだろう。。。としばらく悩んでいましたがやっと原因が分かりました。
ホームディレクトリの下の「Library/Application Support/Sparkle/Transmit」の中にアプリが残っていました。こんな場所にインストールした記憶は全くなかったのですが、調べてみると「Sparkle」というのは自動アップデータ機能を提供するためのフレームワークです。Mac App Store版のTransmitに乗り換えるまで、Webから購入したTransmitを使っていたので、TransmitはSparkleを利用しているようなので、そのときに行ったアップデータの一部が残っていたということのようです。このディレクトリに残っていたアプリを削除すると、Mac App Storeの認識も変わり「インストール」ボタンが押せるようになりました。
もし、同じような現象で悩んでいる方がいましたら、「~/Library/Application Support/Sparkle」ディレクトリは要チェックです。また、アプリをMac App Store版に乗り換えようと思ったときにもチェックした方が良いようです。
▲ページトップへ戻るMOSADeN ONLINE 第21回の記事をアップしました。本日の15時頃公開されます。今回はiOS 5.0で登場したTwitterフレームワークについてです。Twitterフレームワークを使用すると、iOSアプリから簡単にTwitterへ投稿できます。MOSADeN ONLINEはこちら。
▲ページトップへ戻るMSM (MOSA Software Meeting) 2011にご参加いただいた皆様、ありがとうございました。
セッションで使用したスライドやサンプルコードはセッションの最後にお知らせしたURLからダウンロードできるように昨晩(日付が変わる直前でしたが)アップロードしました。URLについては、別途、事務局からもご案内があるかと思います。ダウンロードしてご覧ください。
▲ページトップへ戻るNSViewでカーソルのトラッキングを行うとき、NSViewクラスのaddTrackingRect:owner:userData:assumeInside:メソッドを使っていましたが、Mac OS X 10.5のときにNSTrackingAreaクラスが追加されて、もうちょっとオブジェクト指向的になっていたことに気がつきました。
機能的にはaddTrackingRect:owner:userData:assumeInside:と違いはないように思いますが、updateTrackingAreasという気になるメソッドがあります。
ドキュメントによるとNSViewのサブクラスを作ったときにオーバーライドして、トラッキングエリアの更新を行えるという位置づけのメソッドです。
NSViewのトラッキングエリアの指定は、ビューのサイズが変わったときや移動したときなどに自動的には追従してくれないので、そのことを意識したメソッドのようです。
動作環境が10.5以降のときはこっちを使った方がスマートですね。
▲ページトップへ戻る