これおもしろい

なにはともあれ1日1記事

初期化関数を作りたかったけど...

ブログ続かないぃ…

というわけでちっさいネタで更新していきます。
今日のネタはこれ。"初期化"

遷移しないで画面全体を更新させる為に、特定のプロパティを初期化し直したくて、プロパティ更新の為の初期化関数を作って呼び出す形にしました。
同じ処理なので、宣言時に初期化していた箇所も削除して、今回作った初期化関数をinit関数で呼び出す様にしたところ…

Return from initializer without initializing all stored properties
でめでたくエラーが出ました。

英語に弱すぎてあまり意味がわからなかったので、ググる
(しょうもないけど知らないとできないSwiftの初期化 - 技術はメシのタネ)

init関数の中で関数を使って初期化はできないんですね。
仕方なく元に戻して、今回必要だったところに直に書きました…。

初期化してない時は怒ってくれる仕様だからなのかなぁ?
便利だけど、なかなか厄介さんだなーと思った今日この頃でした。
(実装が微妙ってのも大いにあるけど!)

【悲報】iPhone6でARKitは試せない

久しぶりの更新🤔

もうタイトル通りですね。うっかり忘れてハマってしまいました…。

先日チームメイトからiPhone6を貸してもらい、意気揚々とARKitを試していましたが、どうにもどこのチュートリアル通りにやってもrenderer関数が呼ばれない。 ソース落としてきて試しても呼ばれない。

何でだー??と調べて、SCNSceneのplayingをtrueにするというのが出たけど、その変数はない。 ひとまず初めからちゃんと学ぼうと「ARKit」で調べて出たのが、ARKitの紹介ページ。 そこには「ARKitはiPhone6s以上(SE含む)対応!」の文字が。

…これiPhone6じゃーん!

という悲しい事件が昨日起こりました…😢

対応してないと平面検知が出来なくて、renderer関数に来ない、という事ですね。

自分のSEをiOS11にしようかなぁ。 でも会社でデバッグする時に使うんだよなぁ。 就業前にiOS10に戻す、を繰り返したら端末に負担懸かりそうだしなぁ。 悩みどころ。iPhone6s買うか…?? でも秋にはiOS11に正式に上げられるだろうし…。 もんもん

Nuke読んでて詰まったとこ 7/11〜

@_monoさんが、TwitterでNukeはお手本の様だと仰っていたのもあって、読んでみた
GitHub - kean/Nuke: A powerful image loading and caching framework
読み終えるまで随時更新

読み解けた

internal

internal final class Lock {

クラスのアクセス修飾子
同じライブラリ内ではpublicとして使える
import先の外部からは見えない、という認識でいる

参照:
[iOS 8][Swift] アクセス修飾子を理解する | Developers.IO

DispatchQueue

private let queue = DispatchQueue(label: "com.github.kean.Nuke.Manager")

同期、非同期するにせよ、作っておくタスク
この変数に対して、同期/非同期実行を関数で呼び出す

参照:
Swift3のGCD周りのまとめ - Qiita

private var observers = [() -> Void]()

クロージャの配列 配列の後の()が別物感醸してたけど、配列で良いらしい

参照:
[Swift]クロージャーの使い方 ※swift2.2の記事の為、不可となっているが

subscript

public protocol Caching: class {
    /// Accesses the image associated with the given key.
    subscript(key: AnyHashable) -> Image? { get set }
}

public extension Caching {
    /// Accesses the image associated with the given request.
    public subscript(request: Request) -> Image? {
        get { return self[Request.cacheKey(for: request)] }
        set { self[Request.cacheKey(for: request)] = newValue }
    }
}

これすごくかっこいい
まだざっくりとでも自分の言葉で説明できるほどに理解はしてない
※配列な訳ではない(確保されるメモリはこのクラス1つ分)
2箇所挙げたのは、ここの引数が違うことに気付かなくて数分混乱したから
上の方のは、準拠先のCacheでオーバーライドされている

参照:
サブスクリプト | Swift言語を学ぶ

objc_setAssociatedObject

objc_setAssociatedObject(target, &contextAK, context, .OBJC_ASSOCIATION_RETAIN)

変数をクラスに生やす(外部から)
ランタイムの機能を使っているそう ← 今度調べる
ここで渡している&contextAKが分からない
private static var contextAK = "Manager.Context.AssociatedKey"
第2引数自体がイマイチ分かってない ← 今度試し書きしてみる

参照:
継承を使わずにクラスにプロパティを設定する方法! - VASILY DEVELOPERS BLOG

Result列挙型

public enum Result<T> {
    case success(T), failure(Error)

    /// Returns a `value` if the result is success.
    public var value: T? {
        if case let .success(val) = self { return val } else { return nil }
    }

    /// Returns an `error` if the result is failure.
    public var error: Error? {
        if case let .failure(err) = self { return err } else { return nil }
    }
}

// 以下、実際に使用している箇所. 
// 設定箇所. 
if let data = data, let response = response, error == nil {
    completion(.success((data, response)))    // タプルだよね?. 
} else {
    completion(.failure((error ?? NSError(domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil))))
}

// valueの使用箇所. 
public func handle(response: Result<Image>, isFromMemoryCache: Bool) {
    guard let image = response.value else { return }

valueを呼ぶと、自身(設定箇所で渡されているResult変数)が.successなら、.successの値を返す
swiftの列挙型にまだ慣れていなくてやたら時間掛かった…

参照:
Swiftの列挙型(enum)おさらい - Qiita
Pattern Matching, Part 4: if case, guard case, for case – Crunchy Development

isKnownUniquelyReferenced()

    private mutating func applyMutation(_ closure: (Container) -> Void) {
        if !isKnownUniquelyReferenced(&container) {
            container = container.copy()
        }
        closure(container)
    }

名前通り、参照(※強参照)が1つかどうかを確認する
この関数が何をしようとしているのかは未だ理解できてない

参照:
isKnownUniquelyReferenced(_:) - Swift Standard Library | Apple Developer Documentation

reduce

    public func process(_ input: Image) -> Image? {
        return processors.reduce(input as Image!) { image, processor in
            return autoreleasepool { image != nil ? processor.process(image!) : nil }
        }
    }

コメント読む限り、Image!に変換したinput(=image)を追加した順のprocessorに渡しつつprocess実行したい、ということだと思う(コード的にもそう思う)
ということは、processorは配列だし、for文でも出来る??
けどこっちのがスマート、ってことで合ってるのだろうか?

参照:
Swiftのmap, filter, reduce(などなど)はこんな時に使う! - Qiita

DispatchWorkItem

        let work = DispatchWorkItem(block: closure)
        queue.async(execute: work)

キューの指定が必要ない + 細かい制御ができる 今回は渡したclosureを非同期実行させたいから使ってる

参照:
[Swift 3] Swift 3時代のGCDの基本的な使い方 | Developers.IO

convenience

    public convenience init(maxConcurrentOperationCount: Int) {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = maxConcurrentOperationCount
        self.init(queue: queue)
    }

親クラスのinitの前に処理したい為につけてる

参照:
[Swift] convenienceイニシャライザとdesignated(指定)イニシャライザ - Qiita

willChangeValue/didChangeValue

    override var isExecuting: Bool {
        get { return _isExecuting }
        set {
            willChangeValue(forKey: "isExecuting")
            _isExecuting = newValue
            didChangeValue(forKey: "isExecuting")
        }
    }

プロパティがコードで変更された時に明示的に通知する 変更内容はwillとdidで挟んであげる isExecutingのsetterの中なのだから、通知する必要がなさそうに思ったけど、どこで必要になるのだろう??

参照:
willChangeValue(forKey:) - NSObject | Apple Developer Documentation
Swift で Model を書いてみた (observer編) - Qiita
ヒレガス本の例題を Swift で書いてみる(3) - Qiita

CALayerを設定している意味

    extension ImageView: Target {
        /// Displays an image on success. Runs `opacity` transition if
        /// the response was not from the memory cache.
        public func handle(response: Result<Image>, isFromMemoryCache: Bool) {
            guard let image = response.value else { return }
            self.image = image
            if !isFromMemoryCache {
                let animation = CABasicAnimation(keyPath: "opacity")
                animation.duration = 0.25
                animation.fromValue = 0
                animation.toValue = 1
                let layer: CALayer? = self.layer // Make compiler happy on macOS
                layer?.add(animation, forKey: "imageTransition")
            }
        }
    }

表示する時に綺麗なフェードインをしてくる所以がここか!
不透明度を0から1にするまでのアニメーションを設定している


読み解けてない

CancellationTokenSource::cancel

    public func cancel() {
        if isCancelling { return } // fast pre-lock check
        lock.sync {
            if !isCancelling {
                isCancelling = true
                observers.forEach { $0() }
                observers.removeAll()
            }
        }
    }

ManagerクラスのloadImage関数ののcancelRequest(for: target)でtargetが既に登録されているなら、cancel掛ける、という意味だと思ったけれど…。
CancellationTokenSourceクラスのcancel関数の中で、キャンセル状態に切り替える時にobservers.forEach { $0() }で実行してからクロージャを削除しているところが分からない。

argument passed to call that takes no arguments

数分混乱した。

func getDeviceInfo() -> Observable<Void> {
    return Observable.create { observer -> Disposable in
        let object: DeviceEntity = ...   // 省略
        observer.onNext(object)
        observer.onCompleted()
        return Disposables.create()
    }
}

と書いていて、
onNextのところで
argument passed to call that takes no arguments
と怒られた。

問題だったのは関数の戻り値がObservableだったから

func getDeviceInfo() -> Observable<DeviceEntity>

onNextで入れたいものを返すようにすること

RxSwiftちゃんと勉強しよう…。
いまいちはっきりと分かってない。

@escapingなるものを知った

    func presentAlert(title: String, message: String, completion: @escaping (_ action: UIAlertAction?) -> Void = { alert -> () in }) {
        let alert: UIAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
 
        let action: UIAlertAction = UIAlertAction(
            title: "OK",
            style: .cancel,
            handler: completion
        )
 
        alert.addAction(action)
        self.view?.presentAlert(alert: alert)
}

こんな関数を作ったところ、
Passing non-escaping parameter completion to function expecting an @escaping closure と怒られた。

ここで初めて@escapingという存在を知りました。
引数で渡した時に、渡された関数内で使わず、クロージャを保持する場合は、@escapingをつけなければならないそうです。

今回はpresentAlert関数を持ってるクラスの他の関数で呼んでいて、クロージャの中ではselfを使わないから循環参照は大丈夫。
でも、@escapingとか付くと、よろしくない書き方なのかな((((;゚Д゚)))))))と戦々恐々とする。
レビューしてもらう時に質問しておこう…。

追記: githubで@escapingを調べてみたけど(‘@escaping'とかescapingとかで)、あまり引っ掛からなかった。
やっぱりあまり使わない、というかライブラリとかの時に使うとかの代物なのかなぁ。

(´-`).。oO(今気づいた…これprivateにすべき関数だ…)

参照: すごくわかりやすくて助かりましたmm
Swift 3 の @escaping とは何か - Qiita

決心してから早13日...

 

takattata.hateblo.jp

 というのを13日前に書いた訳ですよ!

1日すら続いてない!

そもそもなぜやろうと思ったのかというと、色々あるんですが、

決定打は@shu223のスライドに出会ったからなんですよね。

http://www.slideshare.net/t26v0748/tech-crunchhackathon-20131111expanded

 

なにはともあれ、業務中に調べたこととか程度のものをまずはザクザク上げていこう...

エンジニアとしての夢を持とう

4月にベンチャー企業に転職して以来、エンジニアとしてどうありたいか?という事をよく考える様になりました。
もちろん成したいことがあって理念に共感したから入りましたけど、技術的な面とか、エンジニアとしての将来に関してはほぼ考えていなかったからです。
気づいた時から始めれば良いことだと思うので、これから自分の強みを開拓&開発していくべく、第一段階としてブログを書こうと思います。
著名な方々もアウトプット大事と再三仰ってますからね😄