Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

Observable

次のようなクラスを定義する。

class Temperature {
    private let eventSubject = PublishSubject<Int>()
    var event: Observable<Int> {
        return eventSubject
    }
    
    func doSomething(x:Int) {
        eventSubject.onNext(x)
    }
    
}

テキストフィールドの編集が終わったタイミングで数を数えるということにしてみた。正しい書き方かはわからない。

        _ = textFiled?.rx.controlEvent(UIControlEvents.editingDidEnd).subscribe { event in
            self.temperature.doSomething(x: self.textFiled!.text!.lengthOfBytes(using: .utf16))
        }
        
        disposeTemp = temperature.event.subscribe(
            onNext: {print("\($0)")}
            , onError: {_ in },
              onCompleted: { print("end")},
              onDisposed: { print("diposed")}
        )

とめたいときはdisposeTempをdispose()すれば良い。

RXSwift

RxSwiftを試してみた。

CocoaPodでインストールした上で以下をインポート

import RxSwift
import RxCocoa

使い方は

        textFiled!.rx.text
            .map {
                guard let text = $0, text.lengthOfBytes(using:.utf16) > 0 else {
                    return ""
                }
                return "\(text)!"
            }
            .bindTo(label!.rx.text)
            .addDisposableTo(disposeBag)

これだけでラベルにテキストフィールドの値を加工したものが即時反映される。

継続モナド

継続モナドはSwiftで段階的に作れる。

1. まず継続渡しの関数を作る。

func getA(complete:(String)->Void) {
    complete("X")
}

2. 継続渡しの関数を引数にとるクラスを作る。

typealias Func<T> = (T)->Void

public struct RDFuture<T> {
    
    public var f:(Func<T>)->()
    
    public func result(_ complete:(T) -> Void) -> Void {
        f(complete)
    }
    
    init(_ f:@escaping (Func<T>)->()) {
        self.f = f
    }
}

これで骨組みはできた。

このように使う

func test() {
    let f = RDFuture(getA)
    
    f.result {
        print($0)
    }
}

これに、bind的な実装をつけることになる。

Realm

Realmを試してみた。便利だ。。

import Foundation
import RealmSwift

class Man : Object { // ObjectはRealmのクラス
    dynamic var name = "" // dynamicはobjective-Cのランタイムを利用して値にアクセスする
    dynamic var age = 10
    let cats = List<Cat>()  // ListはRealmのクラス
    
}

class Cat : Object {
    dynamic var name = ""
    let owners = LinkingObjects(fromType: Man.self, property: "cats")
}

class Test {
    func test() {
        let man = Man()
        man.name = "ho"
        man.age = 5
        
        
        let cat = Cat()
        cat.name = "mi"
        
        
        let realm = try! Realm()
        
        try! realm.write {
            realm.deleteAll()
            realm.add(man)
            realm.add(cat)
            let man = realm.objects(Man.self).filter("name == 'ho'").first!
            man.cats.append(cat)


        }
        

        
        let babies = realm.objects(Man.self).filter("age < 2")
        print("\(babies.count)")
        
        DispatchQueue(label: "background").async {
            autoreleasepool {
                let realm = try! Realm()
                let men = realm.objects(Man.self)
                let man = realm.objects(Man.self).filter("age == 5").first!
                try! realm.write {
                    man.age = 10
                }
                let cat = realm.objects(Cat.self).filter("name == 'mi'").first!
                
                print("\(man.cats.first?.name)")
                print("\(cat.owners.count)")

                let babies = realm.objects(Man.self).filter("age == 10")
                print("\(babies.count)")
                

            }
        }
    }
}

proxy

export USERNAME=
export PASSWORD=
export HOST=
export PORT=
export PROXY=$USERNAME:$PASSWORD@$HOST:$PORT
export http_proxy=http://$PROXY
export https_proxy=https://$PROXY
export ftp_proxy=ftp://$PROXY
export HTTP_PROXY=http://$PROXY
export HTTPS_PROXY=https://$PROXY
export FTP_PROXY=ftp://$PROXY
export no_proxy=
export NO_PROXY=$no_proxy

以下を参照した。
プロキシ下でLinuxを使う際のメモ - Λlisue's blog

viewWillLayoutSubviews

viewWillLayoutSubviewsはviewのlayoutSubviewsの前に呼ばれる。
ちなみにlayoutSubviewsはレイアウト更新タイミング、制約つけたいときはupdateConstraints。

viewWillLayoutSubviewsは結果的にViewWillAppearとViewWillDidAppearの中間で呼ばれることになる。

画面切替

snapshotViewとの組み合わせでいける。

          let currentView = self.view.snapshotView(afterScreenUpdates: true)!
          self.view.addSubview(currentView)
          UIView.transition(with: currentView, duration: 0.5, options: [.transitionFlipFromRight], animations: {
                currentView.frame = CGRect(origin: CGPoint(x:-self.view.frame.width, y:currentView.frame.origin.y), size: currentView.frame.size)
            } , completion: { _ in
                    currentView.removeFromSuperview()
            })

幾つかのメモ 2

ImageButtonはボタン背景がついてしまう。

画像つきボタンはImageViewを使えば良い。

文字付きアイコンはShapeを定義してバッググラウンドに指定する。

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
	<solid
		android:color="@color/hoge"/>
	<stroke
		android:width="1dp"
		android:color="@color/hoge2"
		/>
	<corners android:radius="3dp" />
</shape>

のようなものを作って、textViewのandroid:backgroundに指定すれば良い。

スタイル設定

共通のxmlの色や幅等を共通なものを指定したい場合styleを作りそれを指定するようにできる。

画像回転

		view.setRotation(-90F);