- 投稿日:2019-05-03T23:01:20+09:00
PushKitでVoIPの通知を受ける
今までプッシュ通知を受けるには
didRegisterForRemoteNotificationsWithDeviceToken
でdeviceTokenを受け取ってきましたが、PushKitをつかった通知を受ける場合は、まず- (void)voipRegistration { PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; pushRegistry.delegate = self; pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; }とやっておき、PushKitのdelegateを受けるようにします。
- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(NSString *)type; -(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type; -(void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type;これら3つです。
tokenの登録は
didUpdatePushCredentials
で行います。
[credentials.token description]
として取り出せるので今までと同じようにNSStringとしてPushサーバーのDBなどに保存しておけば良いです。あとはそのtokenに対して、Push通知をしてあげれば、
didReceiveIncomingPushWithPayload
が通知のダイアログなどなしにキャッチできますので、ここでVoIPの着信通知などの処理を行えばよいです。
- 投稿日:2019-05-03T22:31:34+09:00
Swiftで幽霊型を実装する
概要
Swiftで幽霊型を実装する方法を説明します。
※幽霊型は英語でPhantom Type(ファントムタイプ)と呼ばれますが、本記事内では幽霊型で統一します。
幽霊型とは
幽霊型はSwiftのclass、struct、enumのような言語機能として提供される型ではありません。
幽霊型は実装パターンの一種です。実装パターンのため、Swiftに限定されるものではなく、Scala、Haskellなどでも同様の表現があります。(参考: Phantom Typeの紹介)
コンパイル時にしか存在しないという特徴を持つため、幽霊型と呼ばれるようです。
幽霊型の特徴
幽霊型は以下のような特徴を持ちます。
- 型に型パラメータとして付加情報を持たせることにより、コンパイラでの静的チェックを強化する
- 型による制約がコードに表現されるため、コードが自己文書化され、可読性も向上する
- 幽霊型の実装はジェネリクスの型パラメータにすぎないため、実行時には影響しない
もっとも簡単な実装例
幽霊型のミニマムな実装例はこれだけです。ここでenumで表現している理由は、幽霊型はインスタンス化する必要がないからです。caseを持たないenumはインスタンス化することができないという一般的なテクニックを利用しています。
enum ATag {} enum BTag {} struct Hoge<T> { }型引数により、Aという情報を付与できています。
例えば以下のような実装により、ATag情報を持つHogeインスタンスのみを受け入れるような関数を作成できます。func print(hoge: Hoge<ATag>) { print("ATagのみ出力") } let hoge = Hoge<BTag>() print(hoge: hoge) // Extraneous argument label 'hoge:' in callもう少し面白い実装例
以下のような
Cat
型を考えます。struct Cat {}幽霊型によってねこが空腹かどうかの付加情報を表現してみます。
まず、
Cat
型に型パラメータT
を持たせ、ねこの状態をenumで表現します。// ジェネリック型に変更する struct Cat<CatState> {} // ねこの状態を表す幽霊型 protocol CatState {} protocol Runnable {} protocol Eatable {} enum HungryCat: CatState, Eatable {} // 空腹 enum NotHungryCat: CatState, Runnable {} // 満腹これでねこの状態を型情報に持たせることができるようになりました。
catA
インスタンスは空腹で、catB
インスタンスは満腹であることがコンパイラにも理解できるようになります。let catA = Cat<HungryCat>() let catB = Cat<NotHungryCat>()これを利用し、
Cat
型を型制約付きのエクステンションを実装することで幽霊型に応じた実装が可能です。extension Cat where T: Eatable { func eat() { print("食べる") } } extension Cat where T: Runnable { func run() { print("走る") } } let catA = Cat<HungryCat>() catA.eat() catA.run() // Type 'HungryCat' does not conform to protocol 'Runnable' let catB = Cat<NotHungryCat>() catB.eat() // Type 'NotHungryCat' does not conform to protocol 'Eatable' catB.run()より実践的な実装例
【Swift】型を使うという意味を考える (Phantom Typeを通して) - Qiita
こちらの記事では幽霊型をショッピングアプリケーションでの状態管理に利用したり、UserのidやDogのidなどを同じString型で表現せず、複数のIDを幽霊型を利用して識別する方法が示されています。
幽霊型を利用しない場合
逆に幽霊型を利用しないパターンも容易に想像がつきます。例えば、先述のHungryCat、NotHungryCatを個別のstructで定義する場合です。
struct HungryCat: Eatable {} struct NotHungryCat: Runnable {}それぞれの型の固有の振る舞いはそれぞれの型に定義すれば良いですが、共通の振る舞いを安直に実装すると、冗長なコードになります。(
name
プロパティやsleep()
メソッド)struct HungryCat: Eatable { let name: String func sleep() { print("ねる") } } struct NotHungryCat: Runnable { let name: String func sleep() { print("ねる") } }メソッドであればプロトコルエクステンションでの処理の共通化が可能ですが、プロパティはスーパークラスを定義しないと共通化はできません。(スーパークラスの設計の難しさや構造体からクラスに変更する必要が出てくる)
extension Sleepable { func sleep() { print("ねる") } } struct HungryCat: Eatable, Sleepable { let name: String } struct NotHungryCat: Runnable, Sleepable { let name: String }上記のように、独自型を用いるのか、幽霊型を用いて既存の型を拡張していくのかどちらが良いのかは修正による影響範囲なども関係するため、ケースバイケースかと思います。独自型と幽霊型の使い分けなどあればコメントに書いていただけるとうれしいです。
参考
- Swift で Phantom Type (幽霊型) - Qiita
- iOSDC 2017 でさらっと出てきた Phantom Type さらっとやった話 - Qiita
- Phantom Typeでコンパイル時に状態チェックする: shibuya.swift #4 - speakerdeck
- FlowtypeでPhantom Typeを楽しむ - Qiita
- で、出たー!幽霊型だー!(Phantom Type) - Qiita
- F(by) 2017. Denis Shevchenko - The Way to Simplicity: How Haskell Simplifies Code Maintenance.
- Phantom type - HaskellWiki
- 投稿日:2019-05-03T15:45:43+09:00
JSエンジニア必見!アプリ開発の際のReact Nativeことはじめ
開発環境や前提の知識など
事前環境
• Android, iOS のクロスプラットフォーム・アプリ開発フレームワークです。
画面デザインとロジックのコードを共通で利用することができます。
JavaScript でコーディングし、React で画面をデザインできます。・Node.jsやライブラリ管理にnpmなどが活用されます。
・Homebrew
・*watchmanをインストール(よく、忘れがちです)brew install watchmanメリット
Android、iOSでコードが共通化できるので、両方開発する場合は開発効率が良い
JavaScript で開発するため、、Web開発者の学習コストが低い
Facebook, Instagram, CookPad, メルカリ など大手で実績がある。デメリット
アップデート、保守管理が大変
業務で、少し触れていますが、React Native はソースの管理が難しく、
バージョンをあげたりすると、コマンドが通らなくなったりして、意外と神経を使いますおすすめツール
Visual Studio Code
PowerShell (Windowsのみ)
Android Studio (Android アプリのビルドに必須)
Android アプリの IDE
Xcode (iOS アプリのビルドに必須)
iOS や macOS アプリ の IDE
Node.js (必須)
React Native アプリのビルドやデバッグに必要。
yarn (必須)
Node.js のパッケージ・マネージャ。npm の改良版で、置き換えが可能。
必須、と書いたが、npm でも代替は可能。ただしメリットはない。参考URL
React Native開発のすすめ
・https://qiita.com/janus_wel/items/787732d2bf03ed53a3baReactNativeを使ってみる
https://qiita.com/kurohune538/items/fb9f5ff0b005a39fcc27