Objective-C++を使ってMRCで快適に開発する | iOSDC 2017

iOSMacの開発において現在ではARC(Automatic Reference Counting)が前提となっており、MRCの時代と比べて飛躍的に簡単になりました。しかし、開発するアプリによってはMRCでメモリ管理をしたい場面が少なからずあるはずです。そんな時はObjective-C++の力を使って、ARCのように快適な開発をしましょう。

f:id:niwatako:20170915175621j:plain

ユビレジで働いています。

さて、Objective-C++でMRCを使うシチュエーションが果たしてあるのか?はおいておいてこのような話をさせていただきます。

メモリ管理の話と、そして、なぜC++かの話が見えてくると思います。

後半でサンプルコードが出ますが、スライドの下の方にURLがあります。スライドも公開すると思います。

Objective-Cのメモリ管理

MRCでないのはARCです。ObjCで参照カウント方式のメモリ管理をコンパイラがやってくれます。

f:id:niwatako:20170915175750j:plain

DefaultでYESになっています。

f:id:niwatako:20170915175816j:plain

NOにすれば使わないことができますがSwiftはARCだけです。

ARCを使わず自分でメモリを管理するのがMRCです。

f:id:niwatako:20170915175845j:plain

これがどのようなものか見ていきましょう。

f:id:niwatako:20170915175912j:plain

TestClass *value = [[TestClass alloc] init];
[value retain] // 参照カウント2
[value release] // 参照カウント1
[value release] // 参照カウント0

Autoreleaseと言うのもあります。

f:id:niwatako:20170915180016j:plain

[value autorelease] とすることで開放を予約することができ、 @autorelasepool{ } でかこまれた間を抜けると開放されます。

ARCとMRCでクラスを実装する時の違いを見てみます。

プロパティを書いてしまえばいいんですが、手動で実装したとしましょう。ARCです

f:id:niwatako:20170915180111j:plain

MRCです

f:id:niwatako:20170915180143j:plain

deallocでもreleaseをしたり。一つのインスタンスに対してこれだけコードを書きました。当時はみなさん苦労したのではないでしょうか。

そこで利用するのがObjective-C++です。

f:id:niwatako:20170915180227j:plain

Objective-CC++を共存して書けるということです。

f:id:niwatako:20170915180302j:plain

拡張子を .mm にすると書けます。C++との機能の呼び方の違いを見てみましょう。

f:id:niwatako:20170915180344j:plain

だいたいこのような似た機能があります。

どんなコードが書けるのでしょうか

f:id:niwatako:20170915180503j:plain

同じ関数の下2行はC++で書いています。

これはC++です。返り値の型にもC++の型がかけます。

f:id:niwatako:20170915180610j:plain

C++の関数と同じように書けます。

逆にC++のクラス定義にObjective-Cを書くこともできます。

f:id:niwatako:20170915180743j:plain

メモリ管理はどうするでしょう

f:id:niwatako:20170915180755j:plain

CppClass *pointer = new CppClass();
delete pointer

new で作って delete で消します。参照カウントはありません。 1回のnewに対して1回のdelete。

組み込み型と同じような書き方ではこうです。

f:id:niwatako:20170915180937j:plain

Cpp Class value_1;
...... // 書き方はいろいろありますが全部同じです
auto value_5 = CppClass(5)

値型のような扱いで、スコープを抜けると開放されます。

f:id:niwatako:20170915181016j:plain

if の中で宣言すれば、出る時に開放されます。

f:id:niwatako:20170915181048j:plain

メンバ変数はデストラクタが呼ばれると開放されます。

f:id:niwatako:20170915181123j:plain

Objective-CのクラスにC++のメンバ変数を定義するとどうなるでしょう。

[super dealloc] を呼ぶと開放されます。(allocが呼ばれた時点でコンストラクタが呼ばれています)

Objective-Cのオブジェクトを保持するC++のクラスを作るとMRCでも手軽に管理できないか

f:id:niwatako:20170915181230j:plain

サンプルコードの一つのコードです

f:id:niwatako:20170915181315j:plain

objc_ptr.hpp というクラス。チョットデキルひとなら簡単に読めると思います。

こんな構造です。

f:id:niwatako:20170915181354j:plain

shared_ptrはC++で参照カウント方式でオブジェクトを管理するものです。new や delete をいい感じにしてくれるもの。

Objective-CのものをC++でshared_ptrを使えば、開放し忘れないという考えです。

f:id:niwatako:20170915181536j:plain

TestClassをautoreleaseした状態で、objc_ptr にTestClassを保持させます

* 演算子を作って、先頭につければ中身が取り出せるようにしました。

参照カウントをそのまま保持するパターン

f:id:niwatako:20170915181658j:plain

auto で変数の型推論をつかってシンプルに。

autoreleaseを外して保持するパターンです。

f:id:niwatako:20170915181813j:plain

autoreleaseをほうっておくとメモリが溜まっていくので最初から外してしまおうというやつです。使うかどうかは必要次第ということで

これは弱参照で保持します

f:id:niwatako:20170915181911j:plain

強参照されたものを渡すと弱参照で保持します。 lock を呼ぶと強参照で取得できる。既に開放されていれば中身はありません。

weak self を使いたいときのために .to_weak も用意しました。

f:id:niwatako:20170915181959j:plain

objc_ptrをインスタンス変数で使う例です。

f:id:niwatako:20170915182036j:plain

ARCとMRCの違いをお見せした時と同じ構成で作っています。

MRC

f:id:niwatako:20170915182136j:plain

作ったやつを利用

f:id:niwatako:20170915182144j:plain

ほぼARCのように使えるようになっています。

f:id:niwatako:20170915182159j:plain

使うはobjc_ptrを取り回すのが良いと思います。

改良の余地、展望

f:id:niwatako:20170915182257j:plain

ARC環境下かMRCかでretainやreleaseをマクロで切り替えてコードを書くことがありますが、それも吸収して同じ書き方出かけるようになるのではないか

QA

  • Objective-C++とObjective-Cは相性が良いと思うが、どのような必要でこういうことが必要になったのでしょうか
    • オーディオプログラミングを良くするのですが、ARCをONにしていると音に影響がある気がしたことがあって、できるだけARCを避けたい。
      • 音質?スピード?
        • スピードですかね、途切れるような気がしました。ガベージコレクションのときも明らかに影響がありました。なのでARCも試したら、影響がある気がしました。もしかすると私の思い違いかもしれませんが。
  • ライブラリでMRCを使っていて、本体でARCをONにしている場合、本体を触るエンジニアがライブラリでARCで書いてしまう事故がよくある。そういうのの対策方法、良いアイディアはありますか
    • CocoaPodsを使って勝手にやってもらうというのはありませんか。設定が違ってもファイル単位で設定できる。ライブラリをいじることは、、、ありますか?
      • 内製だとあります
        • うーん、それは、知見はないですねぇ。。
  • Objective-C++はどれくらい新しいC++の文法を使えますか
    • C++のバージョン、は、Xcodeのbuild設定で、いま普通に作ると11、14も選べます。
      • 会場から: 「17もいけますよ、互換性を気にしなれば今はサポートが早いです」

SiriKit and Me | iOSDC Japan 2017

去年発表されたSiriKit。Siriにしゃべるだけでアプリが動かせる?と話題になりましたが、実際には使える機能が限定されているので、なかなか使う機会が多くないと思います。 その上、実際にプロダクトにいれようとすると、SiriKitは通常のアプリ開発ではあまり出会わないような困難がいろいろと待ち受けています。 ここでは、実際のプロダクト開発の経験とをもとに、それをうまくのりこえる方法をお教えします。 WWDCAppleのエンジニアに聞いてきた裏技もお伝えします。

f:id:niwatako:20170915173820j:plain

f:id:niwatako:20170915173825j:plain

スタッフと兼ねています、皆さん来てくださってありがとうございます、前夜祭なので食べたり飲んだりしながら楽しんで下さい。

フリーランスiOSエンジニアです。 ボルダリングなどしています。

f:id:niwatako:20170915173912j:plain

SiriKitは1年半ぐらい前に出ました。

アプリの特定の機能を呼び出すことができます。

使っている人は少ないかもしれません。実装した人、手を挙げる人は少ないのではないでしょうか。

逆にユーザーとして、タクシーを呼んだりした人はいますか

3名。。。

みなさんもデベロッパーならぜひ使ってみてくださいね?

f:id:niwatako:20170915174021j:plain

f:id:niwatako:20170915174026j:plain

タクシーの配車をしてみましょう

f:id:niwatako:20170915174108j:plain

f:id:niwatako:20170915174111j:plain

f:id:niwatako:20170915174115j:plain

日本交通さんから使えます。

LineはMessageに対応しています。

f:id:niwatako:20170915174133j:plain

f:id:niwatako:20170915174139j:plain

f:id:niwatako:20170915174213j:plain

これ以外にもレストランをマップで開いて予約したりできます。

OpenTableが対応しています。

f:id:niwatako:20170915174246j:plain

SiriKitを対応する理由

システムのアプリケーションから自分のアプリケ0ションへの導線を確保することができます。

Accessibilityの面でも。

f:id:niwatako:20170915174319j:plain

目が見えない方でも使いやすくなります。

f:id:niwatako:20170915174342j:plain

ピクシブさんの連載漫画、腐男子社長の漫画で、目が見えなくなった主人公がSiriに電話をかけてもらいます。このような役立ち方は良いと思います。

f:id:niwatako:20170915174419j:plain

f:id:niwatako:20170915174429j:plain

HomePod、スマートスピーカーは競争が激しいので、私は次のWWDCでHomePodにSiriKit対応アプリが載ると予想しています。

f:id:niwatako:20170915174506j:plain

SiriKitについて説明します。Frameworkではありません。Intents, Intents UIという2つのフレームワークから実現されます。

f:id:niwatako:20170915174536j:plain

ターゲットとして追加します。

f:id:niwatako:20170915174550j:plain

フレームワーウを追加すると、サンプルコードが最初にあるので、そのまま使ってみることができます。

Intentsを実装する上で

f:id:niwatako:20170915174626j:plain

機能はシンプルですが引っかかるポイントは多いです。

f:id:niwatako:20170915174645j:plain

システムのアプリ上に機能を提供するのがAppExtensionです。

iOS11では23種類位あります。

f:id:niwatako:20170915174714j:plain

配布する時はHostのアプリと一緒にバンドルしてストアに出しますが、実際にユーザーが実行するときには別々のプロセスとして動きます。

f:id:niwatako:20170915174750j:plain

f:id:niwatako:20170915174806j:plain

ポインタのアドレスを片方のターゲットで記録して、別のアプリから同じメモリポインタを呼んでも、中身が0になります。

同じバンドルのターゲット間でも同様です。

f:id:niwatako:20170915174905j:plain

Intentsから本体アプリのメモリは読めません。

f:id:niwatako:20170915174936j:plain

どうやって情報を共有したら良いでしょうか。

ファイルストレージもサンドボックスという仕組みで別々になっています。

f:id:niwatako:20170915174953j:plain

そこで同じデベロッパーの別のアプリ間でデータを共有するAppGroupを使います。

f:id:niwatako:20170915175011j:plain

それから、SiriKitではユーザーからの問い合わせに自然に答えなければなりません。回答まで時間がかかるとタイム・アウトしてしまうので必要なデータのキャッシュなど工夫が必要です。

f:id:niwatako:20170915175038j:plain

またエラーの情報が乏しいです。

f:id:niwatako:20170915175125j:plain

開発スピードも早いので動かなくなることがよくあります。

f:id:niwatako:20170915175150j:plain

スクリーンショットで記録を残しておいたほうがいいです。

英語だと正しく動くが日本語だと動かない、その逆もあります。各言語で試しましょう。

f:id:niwatako:20170915175231j:plain

f:id:niwatako:20170915175259j:plain

f:id:niwatako:20170915175306j:plain

10年ぐらいiOSやっていますがSiriKitは一番苦しかったです。でも絶対HomePodがあると信じています。 皆さんも是非SiriKitやってみて下さい。

QA

  • 一つ一番デバッグで苦しんだことを教えて下さい
    • 同じコードを書いているのに動作が違うのが苦しくて、先週と今週で動作が違う。なんでですかねーって…
      • 差し支えなければどのようなケースか…
        • 差し支えるので申し訳ありませんが…

モバイルアプリ開発エキスパート養成読本 をご恵贈いただきました: 「今の現場のノウハウが生きたまま届く本」

このたび 株式会社技術評論社より出版される モバイルアプリ開発エキスパート養成読本 をご恵贈いただきました!

嬉しくてとにかく高評価してしまいそうですが、早速感想を書かせていただきたいと思います。

f:id:niwatako:20170411042842j:plain

なお、こちらの本はAndroidiOS、それぞれの最新開発事情について書かれていますが、 信仰上の理由により 私はAndroidアプリは1行も書いたことがないので、誠に恐縮ですが、iOS開発者としての視点からの感想のみ書かせていただいております。

ひとことで言うと: 「著者の手元から生きて届いた気がする現場のノウハウ集」!

こちらの本をご恵贈下さったのは、iOSデバッグに定評のある id:dealforest さん。カンファレンスや勉強会では驚きのデバッグ技を次々と繰り出して会場の誰もを感動させる、デバッグの神様(私の中で勝手にそう思っている)のような方です!

そんな id:dealforest さんがデバッグやテストの章を担当されていることをはじめとして、この本ではそれぞれの著者の方々がその方らしい内容の章を担当されているように見受けられました。

今まさに現場で活躍しているノウハウが、著者の方々の手から生きて届いた!!というのが読ませていただいた第一印象です!

モバイルアプリ開発エキスパート養成読本 (Software Design plus)

モバイルアプリ開発エキスパート養成読本 (Software Design plus)

こんな内容です!

(※ 大体です。目次ではありません!iOSについてのみ抽出)

  • 昨今のモバイルアプリ開発動向
  • iOS開発最新環境
    • Swift3.0、iOS10、Xcode8
  • リアクティブプログラミング
    • 入門(概念)、実践(RxSwift)
  • モダンなiOSアプリ設計
    • Genericsを活用した、Storyboard, UITableView, APIとの通信のタイプセーフ化
    • MVC、MVVMとRxSwiftの活用
  • テスト
  • 運用ツール
    • Apple App Analyticsによる分析
    • Crashlyticsによる不具合調査
    • Fabric Betaによるベータテスト
    • Fastlaneによる自動化
    • Google Firebase
      • Analyticsによる分析
      • NotificationsによるPush通知
      • AnalyticsとNotificationを組み合わせたグロースハック

2017年、いまから取り掛かるプロジェクトのよくある(or 早く使いたい) 開発環境・技術・ツールばかりですね!

2017年のデファクトスタンダード集!!

というわけで、プロジェクトをモダン化したい!とか、これから本格開発するぞ!という方におすすめな、デファクトスタンダードがぎっしり詰まった書籍です。

ただ、これらの中でもリアクティブプログラミングは、まだ普及途上かもしれません。

普及途上のリアクティブプログラミングは丁寧に扱われていました!

Swiftにおけるリアクティブプログラミングは、iOS界隈では2016年に大型の事例が聞こえるようになってきて、try! SwiftやiOSDCでもセッションがあったところです。

私の独断と偏見による肌感ですが、アーリーアダプター以降でも、リアクティブプログラミングの勉強を始めたり、実戦投入を検討したりする方が増えつつある頃ではないでしょうか。

そんなリアクティブプログラミングについては、概念を説明、RxSwiftを使って実践、そして設計の章でもう一度活用例が登場、という親切・丁寧・3段構成になっています!

概念の理解から実際に便利に活用できることを実感できるところまで、順を追って丁寧に説明されている印象を受けました。

感想

この本にかかれている内容は、「2017年春、ここまでできていれば安心!」といえる安定感のある(=先端を攻めすぎていない、鉄板となりつつある、標準の範囲で活用が上手い)最新情報だと思います。

やっぱそれだよね〜とか、そうそう、それこないだ導入した!なんて思いながら読ませていただきました。中にはまだそこまでは出来てないんだよねぇ、というものもあったり。

最新の環境、活用したいSwiftの力、知らなきゃ損するテクニック、王道のツール、そして、もう“尖った技術”というよりは“普通の選択肢”になりつつあるリアクティブプログラミングなど。今の最新事情がギュッと詰まっています!

Androidについても同じだけの情報が詰まっているはず…!

ここまで完全にスルーしてきましたが、各話題ごとに、AndroidiOSのがセットで書かれています。つまりご紹介した内容の少なくとも2倍は情報が詰まっていると思います!!(≧ω≦)

すごい!

気になったら…

いますぐ注文

モバイルアプリ開発エキスパート養成読本 (Software Design plus)

モバイルアプリ開発エキスパート養成読本 (Software Design plus)

または、出版記念 Tech Talks を開催されるそうです!!

2017/04/26(水) 神泉(渋谷付近)にて

connpass.com

さいごに

献本いただきありがとうございました!

発売前の本をめくるのはなんだかドキドキしました。

拙文ながら、この本の魅力を少しでもお伝えすることができていれば幸いです!