ページ

ラベル Swift の投稿を表示しています。 すべての投稿を表示
ラベル Swift の投稿を表示しています。 すべての投稿を表示

2019年7月18日木曜日

UILabelをタップ可能にする(小ネタ)

UILabelは rx.tap が使えない

そこで、UITapGestureRecognizer を使ってタップに対応させる
swift
        @IBOutlet private var profileDescription: UILabel!

        ...

        let gesture = UITapGestureRecognizer()
        profileDescription.addGestureRecognizer(gesture)
        gesture.rx.event.asSignal()
            .emit(onNext: { [weak self] state in
                guard let self = self else { return }
                let viewController = XXXXX
                self.navigationController?.pushViewController(viewController, animated: true)
            }).disposed(by: disposeBag)
:warning: 事前に User Interaction Enabled をONにしとかないといけない!
image.png (60.1 kB)

2018年3月10日土曜日

App ExtensionのShare Extensionを試す 【Swift】

App Extension

以下引用
App Extensionには、基盤となるアプリケーションの機能や能力を拡大する働きがあります。ユーザは、他のアプリケーションまたはシステムとやり取りしながらでも、その機能や能力を活用できます。
つまりはアプリの拡張(まんまw)

Share Extension

↓これ
image.png (65.3 kB)

:computer:環境構築


プロジェクトを作成して、Share Extension用のTargetを追加
image.png (120.6 kB)
image.png (70.5 kB)
Targetを追加すると以下のように聞かれる
image.png (31.9 kB)
-> 「Activate」を選択
Targetが追加されると ShareViewController.swiftが追加されている
swift
import UIKit
import Social

class ShareViewController: SLComposeServiceViewController {

    override func isContentValid() -> Bool {
        // Do validation of contentText and/or NSExtensionContext attachments here
        return true
    }

    override func didSelectPost() {
        // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.

        // Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

    override func configurationItems() -> [Any]! {
        // To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
        return []
    }

}

App Groupの設定

もともとのTargetと追加したTargetの Keychain Sharing と App Groups をONにする
image.png (140.3 kB)

Info.plistの編集

扱えるデータ型を定義する
例) テキストを利用する、画像3枚、WebページのURLを1つまでとする場合
  <key>NSExtensionAttributes</key>
  <dict>
   <key>NSExtensionActivationRule</key>
   <dict>
    <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
    <integer>1</integer>
    <key>NSExtensionActivationSupportsImageWithMaxCount</key>
    <integer>3</integer>
    <key>NSExtensionActivationSupportsText</key>
    <true/>
   </dict>
  </dict>

この時点で一回実行させてみる:eyes:

追加したTarget(Share Extension実装用)を選択して実行すると

↑のようなダイアログが表示され、どのアプリケーションから Share Extension を動かすか選択できる
image.png (36.1 kB)image.png (72.7 kB)
ちゃんと表示されている!!!
今は選択すると
image.png (18.3 kB)
↑こんな感じになる

:pencil: 実装


ShareViewController.swift側の実装を後は好きなようにやる
既にあるメソッドの意味
メソッド何をするメソッドか?
isContentValidバリデーション(Postを押せる状態か?)
didSelectPostPostが押された後の処理
configurationItems追加項目のリスト管理

2018年3月1日木曜日

ReduxのSwift実装「ReSwift」を触ってみる

ReSwift

:computer:環境構築


:eyes: 概要


  • アプリケーション全体の状態(State)はツリーの形で1つのオブジェクトで作られ、1つのストアに保存される
  • 状態を変更する手段は、変更内容をもったactionオブジェクトを発行して実行するだけ
  • アクションがどのように状態を変更するかを「Reducer」で行う

Reduxの登場人物

  • Store
    • アプリ内で1個、1つの状態(State)を保持
    • StateへアクセスするためのgetState()を提供する
    • Stateを更新するためのdispatch(action)を提供する
    • リスナーを登録するためのsubscribe(listener)を提供する
  • State
    • アプリケーションの状態を表す
  • Action
    • Storeが保持しているStateの変更内容が記載されているオブジェクト
    • Actionはstore.dispatch()でStoreへ送られる (dispatch: 発信、急送、派遣の意味)
  • ActionCreator
    • Actionを作成する
  • Reducer
    • ActionとStateから、新しいStateを作成して返す
    • Stateを更新することはせず、新しいStateのオブジェクトを作成して返す

:pencil: 実装


簡単なサンプル

超ミニマム実装をやってみます。
  • State
    AppState.swift
    struct AppState: StateType {
        var text: String?
    }
    
  • Action
    InputAction.swift
    struct InputAction: Action {
        var text: String
    }
    
  • Reducer
    AppReducer.swift
    import ReSwift
    
    func AppReducer(action: Action, state: AppState?) -> AppState {
        let state = state ?? AppState(text: "")
        var newState = state
        switch action {
        case _ as InputAction:
            newState = AppState(text: (action as! InputAction).text)
        default:
            break
        }
        return newState
    }
    
  • ViewController
    ViewController.swift
    import UIKit
    import ReSwift
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            appStore.subscribe(self)
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            // 監視削除
            appStore.unsubscribe(self)
        }
    
        @IBAction func onPush(_ sender: Any) {
            var text = appStore.state.text ?? ""
            text = text + "a"
            appStore.dispatch(InputAction(text: text))
        }
    }
    
    extension ViewController: StoreSubscriber {
        typealias StoreSubscriberStateType = AppState
    
        func newState(state: AppState) {
            print(state.text ?? "")
        }
    }
    
  • AppDelegate
    AppDeledate.swift
    import UIKit
    import ReSwift
    
    // アプリで1つのStoreを作成する ←追加
    let appStore = Store(reducer: AppReducer, state: AppState())
    

動作確認

動作自体はただボタンを押したら"a"が追加されてデバッグログに吐かれるというものです。
image.png (9.9 kB)

2016年6月8日水曜日

いつものアラートに飽きた時のオシャレなアラート Sweet Alert iOS


iOSにしてもAndroidにしても標準のアラートは味気ないものです。。
今回はそんな味気ない標準のアラートをシャレたアラートにしてくれる
Sweet Alert iOSを使ってみます。

標準のアラート

まずは標準のアラートです。
sweet_alert_1
はい、いたってシンプルです。

メッセージのみ

ではSweet Alert iOSを使ってアラートを表示させてみます。
まずはシンプルなメッセージのみのアラート
SweetAlert().showAlert("message")
sweet_alert_2
表示する時にアニメーションが付いてリッチな感じです。

タイトル + Success

次はアラートにタイトルを付け、Successのアラートスタイルで表示させてみます。
SweetAlert().showAlert("message", subTitle: "subTitle", style: AlertStyle.Success)
sweet_alert_3
アラートスタイルはenumで定義されており、
  • Success
  • Error
  • Warning
  • None
  • CustomImag(imageFile:String)
の5種類が設定できます。格段オシャレになりました。

ボタンイベント

最後にアラートにカスタムボタンを表示されてみます。
SweetAlert().showAlert("message", subTitle: "subTitle", style: AlertStyle.Warning, buttonTitle:"Cancel", buttonColor:UIColor.redColor() , otherButtonTitle: "OK", otherButtonColor: UIColor.blueColor()) { (isOtherButton) -> Void in
    if isOtherButton == true {

        print("Cancel Button Pressed")
    }
    else {
        SweetAlert().showAlert("OK", subTitle: "subTitle", style: AlertStyle.Success)
    }
}
sweet_alert_4
OKボタンが押されると別のアラートを表示させています。
アラート一つで雰囲気が全然変わりますね〜。



2016年5月14日土曜日

Swiftの中を見てみる 1 - コンパイルの流れ -


最近Swiftを触っているんですが、中をちゃんと見てなかったんで、
この機会に見てみようかと思います。今回はコンパイルに関してです。

コンパイルの流れ

Xcodeではビルドして実行・・・で簡単に実行できてますが、
その時どのようにコンパイルされ実行されているのかを見てみます。
ざっくりとしたビルド時の流れとしては上から順に、
  • Frontend
    C/C++、Haskell、Swiftなどで書かれたソースを構文解析し
    LLVM IR という中間コードを生成する
  • LLVM Optimizer
    様々な最適化を行う
  • Backend
    特定のマシンに基づいた機械語を生成
という流れになっています。
LLVMとは?
任意のプログラミング言語に対応可能なコンパイラ基盤
JavaとJava VMのように仮想マシンをターゲットにした中間コードを出力し、
特定のマシンの機械語に変換します。

Frontend

C/C++, Objective‑CのFrontendにClangというものがあります。
これはAppleがMacOSやiOS用に作成したものです。
コンパイルの流れとしては、、
  • ソースコード -> 抽象構文木(Abstract Syntax Tree、AST) というものに変換
  • LLVM IRを生成
  • LLVM IR -> 機械語を生成
という流れになってます。
Swift用のFrontend
SwiftではClangをより良くして以下のような流れになってます。
  • Swiftのソースコード -> ASTに変換
  • SIL(Swift intermediate Language)(LLVM IRのSwift版)を生成
  • SILからLLVM IRを生成 -> 最後に機械語が生成
Clangに比べてSILのフェーズが追加されています。

実験

Swiftではコンパイルのオプションで上で見てきた、ASTやSILを
出力してくれるオプションが存在します。
そのオプションを使って色々表示させてみたいと思います。
簡単なサンプルのコンパイル&実行
// hello.swift
print(“hello!!”)
↑をhello.swiftとして保存し、
$ swiftc hello.swift # コンパイル
$ ./hello # -> hello!!
コンパイル&実行します。
AST表示
今度はサンプルのASTを表示させてみたいと思います。
$ swift -dump-ast hello.swift
(source_file
  (top_level_code_decl
    (brace_stmt
      (call_expr type='()' location=hello.swift:1:1 range=[hello.swift:1:1 - line:1:21] nothrow
      ・・・
なにやらずらずらっと表示されたかと思います。
SIL表示
次はSILを表示してみます。
$ swiftc -emit-silgen hello.swift | xcrun swift-demangle
sil_stage raw

import Builtin
import Swift
import SwiftShims
・・・
LLVM IR表示
そしてLLVM IR
$ swiftc -emit-ir hello.swift
; ModuleID = '-'
target datalayout = ・・・
アセンブリ表示
最後にアセンブリ表示
$ swiftc -emit-assembly hello.swift
.section    __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 9
.globl    _main
.align    4, 0x90
_main:
.cfi_startproc
・・・
こうしてみると複数のフェーズを経由している事が分かります。
またSwiftからObjective-Cが使えるのも同じLLVM基盤を採用しているからなんですね。