プログラマ英語学習日記

プログラミングと英語学習のまとめなど

【書評】Androidを支える技術(I)

Androidを支える技術(I)

なにかと話題の書籍、「Androidを支える技術(I)」をようやく読み終えたのでちょっとしたレビューでも。

結論からいいますと、 ここ数年読んだAndroid書籍では最高に面白かったです

TL;DR

  • Androidアプリを作るための本ではない
  • 同様により良いアプリの作り方を示す本でもない
  • 内部構造がメイン
  • かなり深いところまで追っており読み応えバツグン
  • 面白かったが、仕事の役に立つかというと…?

レビュー

冒頭にも書いたとおりAndroidの内部構造、一巻は特にイベントと描画周りに焦点をしばった内容です。これがディープなことディープなこと。

「はじめに」からすでにおかしくて、

「執筆中にNougatが出て、バイトコード実行環境が変わり加筆修正を余儀なくされた」

とか他の本ではありえないことが書かれています。この時点でいい意味でやばい本を買ったという予感と期待に胸が膨らみました。

(逆に上記文言で特になにも感じないなら、おそらくこの本は合いません)


第1章はAndroid全体の概要。Androidアプリを開発したこたがない組み込み系エンジニア向けの解説というところです。ここからすでに「何らのGUIシステムでコーディングしたことがある人」前提で話が進んでいきます。UIスレッドとか当然のように出てきます。

そして2章でいきなりLinuxカーネルLinuxカーネルからのイベントを受け取り、Windowに配布する部分の解説ですからんね…カーネル周りの知識はほとんどないですがざっくり概要ぐらいは掴めたのと同時に「こんな仕組みだったのか!」という驚きを感じました。

ここはAndroidエンジニア以外の人の方が楽しいかもしれませんね。少なくともLinuxの知識があったほうが楽しめるのではないかと思います。

中盤がレイアウトや描画周りの解説。ここは(OpenGLを除き)Javaコード部分の解説が主体です。Viewツリーの構築と描画・イベント処理ですね。

ここについてはそこそこコードを追ったことがあるので、把握してた知識で問題なかったことを確認したぐらいです。dispatchTouch/dispatchDraw/onMeasureなどですね。このレベルぐらいなら自分のように、内部構造をちょっと覗いたことがあるという人は多いのではないでしょうか?

もちろん自分が追ってた範囲よりは深い部分の解説があって面白かったですが、アプリを作るぶんに困らない範囲の知識はもっていたのでそこまで新しい知識というわけでもなかったです。

逆に上記のメソッドをみてピンとこないなら 今すぐ注文していいと思います。より自作Viewが作りやすくなるはずです。


そして一番面白かったのが最終章「バイトコード実行環境」

なぜdexがレジスタ型なのかという考察、いかにネイティブコンパイルするか、さらにそれをAndroidバージョンごとにどのように変わっていったか、およびその理由の考察…

本当の読んでて興奮しました。個人的にこの本で一番面白かったのがこの章です。

バイスの進化、ユーザ要求の変化、それらに合わせてAndroidはどのように変わるべきか…著者の異常とも言えるAndroid愛を感じる章です。

本当にここまでAndroidの構造を把握してる人は日本にそうそういないのではないでしょうか?Androidの複雑で膨大な内部構造のコードを読み・理解しているあたり、著者の力量の高さも伺えます。


当然ですが、内容はそこらのAndroidの書籍より数段ハード です。理解が追いつかず、同じ場所を何度も読み返したので読破にも時間がかかりました(それでも理解しきれてない部分が多い…)

でも面白いんですよねぇ。自分の知らない層の話なので本当に面白い。

個人的にですが以下のような人におすすめです。

  • Android開発を年単位で経験している
  • よくライブラリや自作Viewを作る
  • よくView周りのソースを読む

まずある程度Androidの知識がないと厳しいです。昨日今日触り始めました、ではおそらく難しい。

「昨日今日の人」が読むのを止めはしませんが、この本より先に読むべき本はあると思います。本を読む代わりにとにかくコードを書くでもいいです。

逆にある程度なれた人にとってはより最適化されたアプリを作る手助けになるでしょう。


もっともこの本が最適化手法を提示してくれるわけではありません。

ただし、よりAndroidのソースを追いやすくなるのは間違いないです

その結果、より高速で効率のいいアプリを作れるようになる可能性はあると思います。

どの程度直接的に役立つのかはまだ自分もよくわかりません。

しかしいい刺激になるのは間違いないので、「今読む本がない / 次何を読もう?」というAndroidエンジニアには強くオススメしたい本でした。二巻も買います!


ちなみに所々でコラムがあるのですが、Android3.x系ひどい と何度も書いてて笑えましたw 確かに当時のタブレットはいい出来とは言い難かったですからね…

WWDC Cocoa Development Tips まとめ

Cocoa Development Tips

  • 「あなたが知らないCocoaの29のこと」という面白そうな副題がついてたので見てみました。

  • Internationalization

    • Xcode Scheme Editor > Options から言語を設定できる
  • UserDefaults

    • 4つの階層がある
      • Argument Domain / Application Domain / Global Domain / Registration Domain
      • 読み込み時は、先頭から順に問い合わせる
      • 書き込み時はそれぞれの階層で手法が異なる
        • Registration Domain > UserDefaults.standard.register([“key” : value])
        • ↑これは永続化されない
        • Global Domain > defaults write GlobalDomain key -bool value
        • コマンドラインから叩く。コードではない
        • Application Domain > UserDefaults.standard.set(key, value)
        • ↑よく使うもの
        • Argument Domain > 起動時に設定。書き込みはない
  • 役立つUserDefaults

    • -NSViewLayoutFeedbackLoopDebug YES
      • 繰り返し発生しているレイアウトを追跡しやすくなる
    • -NSApplicationCrashOnException YES
      • クラッシュ時の例外をキャッチして表示してくれる
  • UserDefaults + KVO

    • UserDefaultsはKVOで監視できる
//新機能
extension UserDefaulst {
  @objc dynamic var showAtLaunch : Bool {
    return self.value(forKey: "showAtLaunch") as? Bool ?? false
  }
}

let observation = UserDefaults.standard.observe(\.showAtLaunch) { observed, change in 
  //処理
}

  • Base64

    • Data(base64Encoding:) で楽にBase64文字列を変換できる
    • data.base64EncodedStringBase64文字列化可能
  • Asset Catalogs

    • 画像でも LayoutDirection がサポートされている(去年から?)
      • LayoutDirectionごとに画像を出し分けることができる
    • 色域(Gamut)もサポート。sRGBとP3で画像の出し分けが可能
    • iOS11(HighSierra)からは Color もサポート
      • Androidの colors.xml のイメージ
      • 定義した色を Xib で使える他、 UIColor.init?(named:) で取得可能
  • Unit Test

    • XcodeのNewFileからUnitTestを選択することでテンプレートが生成される
  • NSBox

    • NSBoxを拡張して角丸にする
    • boxTypeをseparatorにして区切り線にするなど
    • Mac専用APIなので正直よくわからず…
  • Restorable State

    • こちらもMacOS専用
    • NSResponderに状態を保持させ、再起動で復元させる?
    • restorableStateKeyPathsプロパティを使えば楽になる?
  • CoreData

    • ※もはやRealmの時代だとは思いますが
    • NSPersistentContainerを使えば厄介なCoreData初期化で楽できる
    • 配列を保存したいときは、RelationShip で ToMany を選択する
      • 必要に応じorderedにもチェックをいれる
    • Modelの新バージョンを作り、あとはCoreData側がマイグレーションしてくれる
    • エラーは適切にハンドリングする
      • 特に追加時
  • NSError

    • NSErrorには各種メッセージがあるので、適切にユーザに表示する
    • 自分でエラーを発生させるときも適切にメッセージを設定するように
    • CocoaErrorを使えば楽できる(新規)
    • 専用のドメインを作えばハンドルしやすくなる?
  • SharedKeySets

    • 頻出するキーを渡しておけば高速化できる
    • NSDictionary.sharedKeySet と NSMutableDicitonary.init(sharedKeySet:) をペアで使う
let set = NSDictionary.sharedKeySet(forKeys:["id", "name"])
let dict = NSMutableDictionary(sharedKeySet: set)
dict["id"] = ...
dict["name"] = ...
  • Accessibility

    • VoiceOverはIBから簡単に設定できる
    • Appを1024x640でテストしておく
    • DeveloperToolのAccessibilityInspectorをうまく使う
  • Documents

    • ユーザに保存させる文章にNSDocumentを使えばVersionControlなどいいようにやってくれる?
    • CocoaAPIは使ったことがないのでイマイチつかめず
  • Reporting Exceptions

    • NSApplication reportExceptionをオーバーライドすれば例外をロギングしやすくなる
  • Debugging

    • XcodeのDebug領域をうまく使う
    • View hierarchy, Debug memory graph, simulate location
  • Sound

    • NSButtonにSoundを設定できる

※セッション一覧ページにはiOS/Mac/watchOS/tvOSとあったのですが、思ったよりMacでした。CocoaTipsなので当然かもしれませんが。

【書評】関数プログラミング実践入門

関数プログラミング実践入門

1年ちょっと前に買ったものですが、読み直しのついでにレビューをしてみます。

※残念ながら改訂版ではありません..もちろん個人の主観に基づくレビューですので、そこはご了承ください。

購入動機

  • SwiftやScala/Java8等、関数型の側面が入った言語を触ることが多くなった
  • それに伴い、関数型の知識が欲しかった。より関数型らしく組むには が欲しかった知識
  • 特定の関数型言語の知識は求めていない
  • 上記理由により、汎用的に関数型の知識を扱っていそうなこの本を選定

TL;DR

  • 全体的に

    • 思ったよりHaskell入門本だがやや内容が少ない
    • 6章の数独が見どころ
  • 長所

    • Haskell含む、関数型言語に本格的に興味を持てた (後のelmに繋がる)
    • 6章の「関数型らしい設計方法」は非常にためになった
  • 短所

    • 他言語との実装比較が冗長に感じられた(1章)
    • 各種サンプルが、関数型であるメリットをもっと感じる内容だとより良かった

レビュー

思ったよりHaskellの本だった、というのが正直なところです。タイトルから期待する内容と実際の内容にかなりのズレがあります(個人的印象ですけど)。タイトルが「Haskell実践入門」だったらまた違ったでしょう。(買わなかった可能性は大きいですが)

タイトルに沿った内容らしいのは、

  • 「型付け」などプログラミング全般の話題に触れる0章
  • 関数型らしい設計手法を提示した6章

ぐらいでしょうか?


とはいえ実はこの0章が最も関数型のメリットを解説しているのではないかと思います。

関数型言語の特徴、参照透過性と並行処理の相性の良さ、テストのしやすさなどなど関数型のメリットが分かりやすく提示されています。(関数型言語の、というよりHaskellの、というべきかも)

また、6章も「数独」という入門本にしてはかなり複雑な題材を取りあつかい、どのように設計していくかが述べられておりここも面白かったです。

この手の入門書としては相当高難度な題材といえるのではないでしょうか?しかももろに「アルゴリズム」の話で関数型とも相性がいいです。DBやHTTPが不要な分、完全にロジックに集中できます。

ここは本当に見ごたえがありました。ソースコードも豊富で当時は初Haskellでしたがなんとかなりました。


一方で 残りの章は普通のHaskell解説本です

特に1章が厳しい。いくつかのよくある実装パターンでHaskellとの比較を行っているのですが、「相手言語の苦手な分野と比較している」のは残念な印象でした。

たとえば

  • Rubyには型がないから型のあるHaskellいいでしょ?

    • 前のページで取り扱ってたJavaには型あるんだけど…
  • CだとTuple返せないから複数の値を返したい時不便でしょ?

    • 次のページのJSならできるのでは…? いや、Cこそやりたい放題な気が。

というイメージ。Haskellの優位性をよく分からない理由付けで解説してるだけに感じてしまいました。


残りの章は主にHaskellの文法解説+αです。

Haskell入門書としては「FunctorやApplicativeなど厄介な部分を除き」良書という印象。

翻訳書籍でないので変な日本語に悩まされることもありませんし、各単語の説明もきっちりしてて読みやすいです。

問題はそのへんのつまづきやすい部分をさらっと流してること

この説明だけでIOモナドを扱える人はほぼいないのではなかろうか…? その辺は他の書籍で補完しないと厳しいです。

数独のためのHaskell解説」と割り切ってる感はあります。確かに数独ではモナドを意識して使わないので数独部分を理解するには十分ではありました。(List/Maybeは他言語にもあり、モナドと意識せず扱えるから困らない)


ちょっと厳しい感想になってしまいましたが、読んでよかったと思ったのは間違いありません。これを読んでいなかったらelmは理解できなかった、触ろうとも思わなかったはずです。

ただしHaskell入門としては明らかに足りていません。特にモナド周り。ここは注意してください。

しかし6章の数独はそれをひっくり返すぐらい面白かった。先ほども述べたとおり、1-5章はこのための準備と割り切る必要はあると思います。

こういう内容が豊富でもっと具体的な設計手法を見れたら/試せたらより良かったと思います。


この数独を経験することでかなりオブジェクト指向での組み方が変わりました。具体的には「参照透過性のあるメソッド」「ないメソッド」を分離したくなる癖が付きました。(参照透過性のあるstaticメソッドがすごい増えた)

Androidでの簡単な例だと以下のようなイメージです。

//before
if (state.isActive && !state.isLoading) {
  button.setText("送信");
} else {
  button.setText("通信中");
}


//after
static String getButtonText(State state) {
    return (state.isActive && !state.isLoading) ? "送信" : "通信中";
}
String text = getButtonText(state); //なぜか一旦変数に格納したくなる症状も出た
button.setText(text);

とにかくsetTextは1箇所に限定したくなる癖がつきました

コードとしては若干面倒になってますが、副作用を伴う操作は極力減らしたい思考に変わりました。


冗長な面やHaskell入門として足りない面はありますが、このような考え方をかえるきっかけとなった本なので良かったです。

特にelmにつながったのは大きい。(少なくともこの本で得た知識おかげである程度なんとかなったのは事実)

ターゲットとする読者層は狭い気はしますけど、上記のような考えかたに触れてみたいのでしたらオススメです。

逆に本格的にHaskell(含む他の関数型言語)に触れたい、商用投入したい/してるプロダクトに触れる必要がある、というのでしたらその言語に特化した他の本を購入されたほうがいいかと思います。

WWDC2017 Introducing ARKit まとめ

iOS11の大きなウリの一つ、ARKitのセッションです。

動画はこちら

Introducing ARKit

ARとは?

  • Virtualな物体をPhysicalな世界に配置すること
  • ポケモンGOを始めとするデモ

ARKit

  • 概要

    • Mobile用AR Platform
    • High level API
    • A9以降搭載のiOSバイスに対応(6s以降)
  • 3つの機能がある

    • Tracking
      • 実世界の座標追跡
      • カメラ画像からの移動変化量
      • 特殊なセットアップ不要
    • Scene Understanding
    • Rendering
      • 楽に組み込める
      • ARViewを使えば、SceneKit/SpriteKitから作成できる(?)
      • Metalによるカスタムレンダリング
  • Unityに組み込まれている

API概要

  • ProcessingとRenderingに分かれる

    • RenderingがMetalやSceneKit
    • ProcessingがAR-Kit
      • 内部でAVFoundationやCoreMotionを用いる
  • ARKit

    • Session-based API
    • ARSessionConfiguration → ARSession と作成する
    • ARSession が ARFrame を生成
    • ARFrame からレンダリングに必要な情報を取得する
  • ARSessionConfiguration

    • ラッキングしたい情報を設定する
    • ARSessionConfigurationは回転情報のみ
    • Subclassに ARWorldTrackingSessionConfiguration
      • 座標移動も検出可能
    • バイスによるサポート情報も取得できるので切り分ける
if ARWorldTrackingSessionConfiguration.isSupported {
  configuration = ARWorldTrackingSessionConfiguration()
} else {
  configuration = ARSessionConfiguration()
}

** ARSession * ARプロセスの管理 * run / pause など * ARSessionDelegate で更新された ARFrame を受け取る

** ARFrame * ARレンダリングに必要な情報がある * カメラ画像 * トラッキング情報 * Scene情報 * ARAnchor * 実世界のポジション * ARSessionに追加/削除する

Traking

  • ARKitは座標だけでなく、「実世界の距離」も計測する

    • セッション開始時点からの位置になる
    • カメラから複数の特徴点を抽出、その位置差分で位置を出す
      • 加速度センサも活用している
  • サンプルコード

let session = ARSession()
session.delegate = self

let configuration = ARWorldTrackingSessionConfiguration()
sesison.run(configuration)
  • ARCamera
    • 仮想的なカメラ情報を提供するオブジェクト
    • Transform/TrackingState/Camera intrinsics

Demo

  • デモで気になったクラスをピックアップ

    • ARSCNView : ARシーンレンダリングの便利クラス
      • SceneKitをはめることができる
      • arScnView.scene = scnView
    • UITapGestureでタップ判定可能
  • タップでスクリーンキャプチャを画像としてSceneに追加するサンプル

func handleTap(...) {
    guard let currentFrame = sceneView.session.currentFrame else {
        return
    }
    //キャプチャした平面Object作成
    let imagePlane = SCNPlane(width: sceneView.bounds.width / 6000,
              height: sceneView.bounds.height / 6000)
    imgPlane.firstMaterial?.diffuse.contents = sceneView.snapshot()
    imgPlane.firstMaterial?.lightingModel = .constant

    //シーンに追加
    let planeNode = SCNNode(geometry: imagePlane)
    sceneView.scene.rootNode.addChildNode(planeNode)

    //カメラの10cm先に配置
    var translation = matrix_identity_float4x4
    translation.column.3.z = -0.1
    planeNode.simdTransform = matrix_multiply(currentFrame.camera.transform, translation)
}

Trackingの品質

  • カメラの環境に大きく左右される

    • カメラに何もうつっていないとトラッキングが中止
    • 「品質のいい」適度に複雑なカメラ画像が必要
    • 動きのあるシーンに弱い
      • 子供が動き回るなど
  • Trackingの状態

    • Not available : 開始直後はコレ。トラッキングの情報が不足してる
    • Normal : トラッキング可能
    • Limited : 真っ白壁など、一部情報がうまく取れない
    • Delegateで検出可能
func session(.., cameraDidChangeTrackingState camera: ARCamera) {
    if case .limited(let reason) = camera.trackingState {
        ...
    }
}
  • Trackingの中断
    • アプリがBackgroundに移動、iPadのMulti-Taskingで中断する
    • Delegateで検出し、表示を切り替える
func sessionWasInterrupted(...) {
    showOverlay()
}
func sessionInterruptionEnded(...) {
    hideOverlay()
    //必要に応じAR処理を再開
}

Scene Understanding

  • バーチャルな物体を配置するときに必要な情報のこと

    • 平面検出
    • ヒットテスト
    • 光量推定
  • 平面検出

    • テーブルのような水平面を検出できる
    • 複数のフレーム情報から計算する
    • 広さを測定できる
    • 面をマージできる
    • ARWorldTrackingSessionConfigurationの planeDetection を使う
      • 現状、 .horizontal しか値がない模様
  • ARPlaneAnchor

    • 平面が検出されるとDelegateが呼び出される?
    • 3軸回転、中央、広さを保持している
  • HitTest

    • カメラからのみた特定の直線が実世界平面のどこに位置するかを調べる
    • 4つの種類がある
      • Existing Plane Using Extent: 平面の位置/広さを考慮したヒット位置
      • Existing Plane : 平面の広さが無限とした場合のヒット位置
      • Estimated Plane : まだ平面が検出されてないときに使う
      • Feature Point : 面が小さいときに用いる(イレギュラーなケースらしい)
    • 画面の座標ベースでテスト可能(0,0が左上、1,1が右下)
  • 光量推定

  • 画像ベースの光量推定
  • 1000ルーメンがデフォルト
  • Configurationで設定する

構成

  • SceneKit/SpriteKit/Metalのいずれか

  • SceneKit

    • ARSCNView
    • カメラ画像を表示する
    • SCNCameraが人にあわせ移動する
    • 自動でLightingされる
    • SCNNode が ARAncher にマップされる
  • SpriteKit

    • ARSKView
    • SKNode が ARAnchor にマップされる
    • SpriteKitは2D描画用
    • 物理計算にテーブルを使うなどが出来る(?)
  • Metal


SceneKitで配置するだけで動くのは良さそうですね。3Dはあまり経験がないので厳しいと思っていたのですが、結構簡単にできそうでちょっと興味わいてきました

WWDC Introducing Drag and Drop まとめ

今回はiOS11の目玉といえるドラッグ&ドロップ機能のセッションです。

他にもドラッグ&ドロップはセッションが多いので、Appleの気合のいれようが伝わってきますね。

とりあえずIntro部分のセッションを。

Introducing Drag and Drop

ビデオは こちら

Drag&Dropのコンセプト

  • Drag&dropとは?

    • タッチによるデータの移動・コピー
  • Drag&Dropのゴール

    • 素早い応答。非同期取得
    • セキュリティ。アクセス制限など
    • マルチタッチで直感的に操作できる
  • 基本的にiPad向けの機能

    • iPhoneでは同一アプリ内に制限される

API概要

  • 4つのフェイズがある
    • Lift : 長押しでドラッグ可能になった状態
    • Drag : プレビューが移動してる状態。
    • SetDown : キャンセル、もしくは転送先の決定
    • DataTransfer : ターゲットへのデータ転送

Drag元のAPI

  • DragInteraction 系APIが追加
    • UIDragInteraction, UIDragInteractionDelegate
    • UIDragItem
let view : UIView = ...
let delegate : UIDragInteractionDelegate = ...
let dragInteraction = UIDragInteraction(delegate : delegate)
view.addInteraction(dragInteraction)
  • Delegateの役割

    • Lift時に、UIDragItem を返す
    • データが無い場合はDragフェイズ終了。
  • UIDragItemとは?

    • 以下の2つを持つ
      • Dragプレビュー
      • NSItemProvider

Drop先のAPI

  • UIPasteConfiguration が追加
    • 対応するデータ種別を指定する
    • Drop対象のViewに追加する
let config = UIPasteConfiguration(typeIdentifiersForAcceptingClass : NSStrnig.self)
view.pasteConfiguration = config

//UIViewを継承して作る? UIResponderのメソッドだった
override func paste(itemProiders: [NSItemProvider]) {
}
  • UIDropInteractinoDelegate で受け取りを行う
    • 受け取り可能かどうかを指定するのもこのDelegate

フェーズ詳細

Lift

  • ロングプレスで移動可能になった状態
    • ドラッグ待ち
    • Delegateで「移動するデータとプレビュー用View」を返す
//アイテムの決定
func dragInteraction(_ interaction: UIDragInteraction, 
                     itemsForBeginning session: UIDragSession) -> [UIDragItem] {
    let itemProvider = NSItemProvider(object: "Hello World" as NSString)
    let dragItem = UIDragItem(itemProvider: itemProvider)
    return [ dragItem ]
}
//プレビュー
func dragInteraction(_ interaction:UIDragInteraction,
          previewForLifting item:UIDragItem,
          session:UIDragSession) -> UITargetedDragPreview? {
  let imageView = UIImageView(image: UIImage(named: "MyDragImage"))
  let dragView = interaction.view!
  let dragPoint = session.location(in: dragView)
  let target = UIDragPreviewTarget(container: dragView, center: dragPoint)
  
  return UITargetedDragPreview(view: imageView,
       parameters:UIDragPreviewParameters(),
       target)
}
//リフトアニメーション
func dragInteraction(_ interaction: UIDragInteraction,
              willAnimateLiftWith animator: UIDragAnimating,
              session: UIDragSession) {
  animator.addAnimations {
    self.view.backgroundColor = UIColor.gray
  }
  animator.addCompletion { position in
    if position == .end {
      //リフト完了
    } else if position == .start {
      //リフトキャンセル。元に戻る
    }
  }
}

Drag 送信

  • ドラッグが成功したかどうかに応じてDelegateを実装する
func dragInteraction(_ interaction: UIDragInteraction,
      previewForCancelling item: UIDragItem,
      withDefault defaultPreview: UITargetedDragPreview) -> UITargetedDragPreview?

func dragInteraction(_ interaction: UIDragInteraction,
      item: UIDragItem,
      willAnimateCancelWith animator: UIDragAnimating)

func dragInteraction(_ interaction: UIDragInteraction,
      session: UIDragSession,
      didEndWith operation: UIDropOperation)

Drag 受信

  • 移動先が「データを受け取れるか」を返す
    • DropInteractionDelegate
//sessionをHandleできるかどうか
func dropInteraction(_ interaction: UIDropInteraction,
        canHandle session: UIDropSession) -> Bool {
    return session.canLoadObjects(ofClass: UIImage.self)
}
//handle可の後、Viewに入った時に処理可能かどうか
func dropInteraction(_ interaction: UIDropInteraction, 
                  sessionDidUpdate session: UIDropSession) -> UIDropProposal {
    return UIDropProposal(operation: UIDropOperation)
}
//
func dropInteraction(_ interaction: UIDropInteraction, sessionDidExit session: UIDropSession)
  • DropProposalは4種類ある

    • cancel
    • copy
    • move
      • これは同一アプリ内限定
        • 移動するように作り手があわせる必要がある
      • 送信元が「move可能」とする必要がある
    • forbidden
      • Cancelににてるが、特殊なバッジがつく
      • 利用例: ReadOnlyなフォルダに移動させようとした場合
  • SpringLoading(レインボーカーソルと訳すべきか?)

    • UIButtonに追加
let button = UIButton()
button.isSpringLoaded = true
let springLoadedInteraction = UISpringLoadedInteraction { (interaction, context) in
  //長時間の処理
}
view.addInteraction(springLoadedInteraction)

Drop

  • drop後は dropInteraction が呼び出される
    • データを読み込む場所
func dropInteraction(_ interaction: UIDropInteraction,
                     performDrop session: UIDropSession) {
    session.loadObjects(ofClass: UIImage.self) { objects in
        for image in objects as! [UIImage] {
           self.imageView.image = image
        }
    }
}

デモ

  • 動画29分からコードを交えながらのデモ

    • コルクボードに写真をおくサンプル
    • 気になった部分のみメモ
  • 同一アプリ判定

    • DropSessionで同一アプリ内か外部アプリかで処理分岐が必要になる
    • アプリの仕様によりますけど
//同一アプリ内なら移動、別アプリからならコピー
func dropInteraction(..., sessionDidUpdate ...) -> UIDropProposal {
  let operation: UIDropOperation
  if session.localDragSession == nil {
    operation = .copy
  } else {
    operation = .move
  }
  return UIDropProposal(operation: operation)
}

//Drop後
func dropInteraction(..., performDrop ...) {
  if session.localDragSession == nil {
    //コピー
    dropPoint = session.location(in: interaction.view)
    for dragAtime in session.items {
      loadImage(dragItem.itemProvider, center: dropPoint)
    }
  } else {
    //ボード内での移動、データコピーは不要
  }
}

//Dropアニメーション
func dropInteraction(_ ...   previewForDropping: ...) {
   if session.localDragSession == nil {
     //外部ならなにもしない
   } else {
     //内部なら移動処理
     return defaultPreview.retargetedPreview(...)
   }
}

WWDC What's New In Swift まとめ

早速elmのほうがネタ切れになってきました…やると分かるんですが、 一線を超えると本当に簡単な言語 であまり紹介するTipsがないんですよね。

組み方もいわゆるReduxが強制されますし、Middlewareもフレームワーク内蔵の方法で完結するので、組み方の選択肢があまりないというのも一因です。

ですのでちょっと趣向を変えてネイティブアプリの紹介をしていきたいと思います。

当面のテーマは iOS

WWDCの気になるセッションの概要を書いていきたいと思います。

続きを読む

肥大化するModelTreeとどう戦うか(が分かっていない)

だんだんelmのサンプルが大きくなってきました。Natigationも導入し、いわゆるSPA化してます。

ここで問題になってきたのが、「どう巨大なTreeを管理するか」

言語の難しさの壁を越えたら次は他言語でもあるあるな問題に遭遇しました。

続きを読む