*

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(Xcode5でも同様)でアプリ開発をしていて、少し複雑な事をしようとするとデリゲートと言

記事を読む

iOS(Xcode6とObjective-C)におけるマルチスレッド処理の実装方法その1[NSThreadクラスの簡単な利用例]

「iOS(Xcode6)におけるマルチスレッド処理の実装方法その1」に引き続きiOSに置けるマルチス

記事を読む

Xcode5でSchemeを利用する。[後編]

「Xcode5でSchemeを利用する。」の続きの「Xcode5でSchemeを利用する。[後編]」

記事を読む

iOS(Xcode6とObjective-C)におけるマルチスレッド(非同期)処理の実装方法その2[GCD(Grand Central Dispatch)の利用]

本エントリーではGCD(Grand Central Dispatch)を利用したiOSのマルチスレッ

記事を読む

Xcode5でUnitTest(XCTestフレームワーク)を利用してみる。

Xcode5(iOS7対応バージョンの統合開発)を利用するので、当然言語はObjective-Cです

記事を読む

Xcode5&Objective-CでUITableViewでUINibを使ったカスタムセル(UITableViewCell)を利用する方法

本エントリーでは、Xcode5のテーブルビューにUINibを使ったカスタムセル(UITableVie

記事を読む

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

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

記事を読む

Xcodeの使い方[エディタエリアのJump BarのThe related items menu]

Xcode5(iOS7対応バージョンの統合開発)の「エディタエリア」の使い方のエントリーとなります。

記事を読む

Xcode5を軽快に利用するためのショートカット[基本編]

「Xcode5のエディタエリアの説明 」 「Xcode5のエディタエリアの説明 [中編]」 「X

記事を読む

Xcodeのユーティリティエリアの使い方[ソースファイル表示時]

本エントリーでは、Xcodeの「ユーティリティエリア」の使い方を説明させていただきます。 利用

記事を読む

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 ↑