*

Objective-Cでコールバック処理を@Selectorで実現する方法

公開日: : 最終更新日:2016/12/05 Objective-C


スポンサードリンク



最近はSwiftばっかり読み書きしていますが、既存のライブラリをカスタマイズして使うことも多いので
Objective-Cの知識もかなりの期間は必要になるんでしょうね。

ということで、本エントリーでは@Selectorを用いてコールバック処理を実現する方法を説明させていただきます。
まずは、コールバックとは言えない@Selectorの利用方法を説明させていただいた後に、
コールバックっぽい利用方法の説明をさせていただきます。

コールバックとは言えない@Selectorの利用方法

コールバックとは

コールバックを文字で説明すると。

例えばMicrosoftさんとQ&Aサポート契約結んでいて、なんかこのAPIの仕様おかしくないですか?
とのインシデントを上げる電話をサポートの受付窓口にしますよね、この時点では現象の概要を聞いてもらって
担当エンジニアから折り返しとなりますよね。これがコールバックです。
ってとっても強引・・・

何を表現したいかと言うと、電話をつないだまま、コールセンターの受付のお姉さん(最近はお兄さんの時もたまに)
と話しながら、裏でMSさんの担当エンジニアが決まり、その人が電話に出て、詳細な内容を話して、
またこちらは待ちに入り、既知の事例があればその話を担当エンジニアから聞く。
まあどちらにしても継続調査になる確率が高いですけど・・・

繁忙期(MicrosoftさんのQ&Aサポートの)であれば、担当エンジニアのアサインがすぐにできないこともありますよね。
どう考えても担当エンジニアのアサインを電話をつなぎながら待ってるのは時間の無駄ですよね。
担当エンジニアがアサインされた時点でコールバッグ(電話)してもらうのが現代社会の常識です。

プログラマブルな例ですと
あるメソッドを呼び出したら、制御は呼び出し元に戻るが、あるメソッドの最後に指定したコールバックのメソッドが呼び出される。といった感じでしょうか。

Webアプリを例にすると、検索ボタンを押すと、200件毎にサーバから結果を取得し、描画用のコールバックメソッドが呼び出されて画面に反映され、その間は利用者はどのボタンでも押せる状態にあるといった感じでしょうか。

とどうでも(よくない?)よい例が長くなりましたが、本題に入ります。

コールバックとは言えない@Selectorの利用例

利用例は以下の図のようになると思います。

スクリーンショット 2014-07-17 22.01.22

図のままですが、ViewControllerからWorkerクラスのインスタンスに対して
[Worker funcA:self selector:@selector(callbackAction:title:error:)]を呼び出すと
funcAの処理の最後にViewControllerのcallbackActionが呼び出されます。
(説明を簡単にするためにインスタンスとクラスの違いを明確にしていません。)

これでは完全な直列処理です。
とはいえ、まずは直列処理での@Selectorの利用例を説明させていただく方が理解して易いと思います。

コールバックとは言えない@Selectorの実装例

@Selectorを利用しているけど、利用者がボタンを押して処理が終わるまでずっと待たされる処理の
シーケンス図を書いてみました。

スクリーンショット 2014-07-18 15.15.14

この処理でポイントとなるのが、WorkerクラスのfuncAメソッドになります。

処理を行っていない時の画面は以下のようになります。
スクリーンショット 2014-07-18 15.19.52

処理中の画面は以下のようになります。
スクリーンショット 2014-07-18 15.20.08

ViewController.h

ViewController.m

Worker.h

Worker.m

コーディング上のポイントは
startメソッドで、WokerのfuncAの引数に
self(ViewControllerのインスタンス)と
@selectorを利用してViewControllerのcallbackActionメソッドを渡している部分と
[_worker funcA:self selector:@selector(callbackAction:title:error:)];

WorkerのfuncAのメソッドの引数の定義方法です。

idは特に説明しなくても良いと思いますが、問題はSEL型です。
SEL型とは純粋な任意の1つのメソッドの定義を格納する型です。
NSInvocationを利用してSEL型のcallbackSelectorを呼び出す場合は、NSInvocationのインスタンスinvocationに対して

を呼び出します。

SEL型は任意のクラスの任意の1メソッドを意味しますが、SEL型自体は、どのインスタンスにも関連はありません。
よって呼び出す時にレシーバとしてインスタンスを指定する必要があります。
この処理が以下の1行です。

NSInvocationを利用したSEL型の呼び出しの場合は引数が3つ以上指定可能です。指定方法はコードをご覧いただければ問題なく理解できると思います。

実行時のログは以下の通りです。先ほどのシーケンス図の通りで、処理は直列となっていいます。
直ぐ終わると面白くないので途中で10秒のスリープ入れてますけど。

コールバックと言える@Selectorの利用方法

Worker.mをすこし変更するだけですが、シーケンス図としては以下のようになります。
スクリーンショット 2014-07-24 16.25.35

Worker.m

funcAを並列で実行するように、GCD(Grand Central Dispatch)とBlocks(ブロック)記法を利用して別スレッド化しました。

ちなみにですが、Cocoaプログラミングでは描画処理はメインスレッドのみでしかできないです。
.NET Frameworkでは色々考慮しないといけないですが、別スレッドでも操作できるのですが、
そのくくりを言語として入れるのはバグが発生しにくい考え方なので共感できます。

dispatch_asyncの詳細につきましては、
公式の「スレッドプログラミングガイド」を参照ください。

これで実行(処理開始ボタンタップ)すると制御がユーザに速攻戻ります。
といっても、こんな貧弱な画面では何の意味もないですが・・・

以下が実行時のログとなります。

変更前のログではstart start→コールバックの呼び出し終了→start endとなっていましたが
変更後のログではtart start→start end→コールバックの呼び出し終了となっています。

スレッドIDもメインスレッドのIDである60bは以下の2行だけです。
60b start start
60b start end

以上で「Objective-Cでコールバック処理を@Selectorで実現する方法」は終了です。


スポンサードリンク

Googleアドセンス

Googleアドセンス




関連記事

Xcodeの使い方

Objective-Cでコーディングを行うための統合開発環境のXcodeの利用方法のエントリーです。

記事を読む

Xcode(Objective-C)のデリゲートとプロトコルの使い方[前編]

Xcode(Xcode5でも同様)でアプリ開発をしていて、少し複雑な事をしようとするとデリゲートと言

記事を読む

Xcode&Objective-Cの文字列処理をユニットテスト(XCTestフレームワーク)で確認する。[NSStringを数値に変換する方法]

「Xcode&Objective-Cの文字列処理をユニットテスト(XCTestフレームワーク)で確認

記事を読む

Xcode5&Objective-Cでセグエを利用して画面遷移を実現する。[前編:モックの作成]

iPhoneアプリの画面遷移と言えば、真っ先に挙がるのが「ナビゲーションコントローラ」なのですが

記事を読む

Xcode5のナビゲーションエリア[プロジェクト、シンボル、検索]の使い方

Objective-Cでコーディングを行うための統合開発環境のXcodeの利用方法のエントリーです。

記事を読む

Xcode5でイメージ(画像)を表示&操作する[前編]

Xcodeでアプリ開発を行う時に、イメージ(画像)の表示は必須な処理であると言えます。 前回のエン

記事を読む

Xcode&Objective-Cの文字列処理をユニットテスト(XCTestフレームワーク)で確認する。[NSStringの比較]

前回は、NSStringの定義、分割、検索の各処理を確認しました。 二回目は、NSStringの比

記事を読む

iOS(Xcode6)におけるマルチスレッド処理の実装方法[iOSのマルチスレッド処理の概要]

iOSにおけるマルチスレッド処理の実装方法を数回に分けて説明させていただきます。 開発環境のXco

記事を読む

Xcode5で画面にナビゲーションバーを配置して利用する。

今回は「ナビゲーションバー」をiPhoneアプリの画面に配置して利用する方法を記載させていただきます

記事を読む

Xcode6からはProjectName-Prefix.pchは自動的に生成されませんが、それでもpchファイルを利用したい時の利用方法

小ネタですが、Xcode6からはProjectName-Prefix.pchは自動的に生成されなくな

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

動画で英語を学習できるiOSの無料アプリCapTubeをリリースいたしました。

個人では初となるiOSアプリをリリースいたしました。 何度もリジ

no image
Ruby on rails4系でBootstrapを利用するためのtips

MacでRuby on rails4系のBootstrapを利用しよう

no image
Java、Eclipse、JUnit関連のエントリーの移行のお知らせ

Java、Eclipse、JUnit関連のエントリーは http:/

iOS8開発者向けお勧め本紹介[詳細! Swift iPhoneアプリ開発 入門ノート Swift 1.1+Xcode 6.1+iOS 8.1対応]

iOS7開発者向けお勧め本紹介を以前に紹介させていただきまいたが、今回

Swift入門(Xcode6のXCTestフレームワークで学ぶ) 第二回「関数(メソッド)とクロージャーの利用方法」

前回はSwiftの概要をザックリと説明させていただきました。 今

→もっと見る

Optimization WordPress Plugins & Solutions by W3 EDGE
PAGE TOP ↑