20190503のiOSに関する記事は3件です。

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の着信通知などの処理を行えばよいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
}

上記のように、独自型を用いるのか、幽霊型を用いて既存の型を拡張していくのかどちらが良いのかは修正による影響範囲なども関係するため、ケースバイケースかと思います。独自型と幽霊型の使い分けなどあればコメントに書いていただけるとうれしいです。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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/787732d2bf03ed53a3ba

ReactNativeを使ってみる
https://qiita.com/kurohune538/items/fb9f5ff0b005a39fcc27

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む