これおもしろい

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

初potatotips行ってきました!

potatotipsにブログ枠で行ってきたんです!

potatotips.connpass.com

が、大大大大遅刻です!すみません!!!😭😭😭 ブログ上げるのが遅くなって運営さんには本当に申し訳ないです…すみません… 以後本気で気をつけます… わからないところを調べながらやってると時間かかりますね…慣れが必要なのかなぁ…(猛省)

感想

ブログを上げるのは遅くなりましたが、本当に良い勉強会でした!
LTの内容も勿論のこと、すごく話しやすい雰囲気だったり、参加されてる方たちのモチベーションも高いからですかね?出られて良かった^^と思いました。
是非行ったことない方、狙って行ってみることをお勧めします!
自分もまたブログ枠で確実に狙っていきたいと思います。(次こそ3日以内にはブログ上げる…!!)
あ、あと、マネーフォワードさんの社内が格好良過ぎてテンション上がりました。

自分の感想はここまでにして、LTの内容に行きますね!(注意: 基本的にスライドを見れば内容が分かると思うので、自分の感想程度のことしか書いてません。)
ちなみにtoggeterはこちら。ありがたし。 togetter.com

LT

1. iOSのBLEでハマった事 +Tips

Tomoya Miwa (@tomoya0x00) | Twitter

qiita.com

BLE = Bluetooth Low Energy
無線PAN技術であるBluetoothの仕様における、バージョン4.0の呼称である。

とのことで、Bluetoothの話でした。 正直分からなかったのですが、バイトの話が出てきてテンション上がりました。 公式から出ているドキュメントが一番強い、ということを学びました。

2. Annotation Processing

仙波拓 (@takusemba) | Twitter

speakerdeck.com 資料が英語!!かっこいい。 Javaの機能だそうです。 Javapoetを使うと良い。 すみません、正直門外漢すぎて分かりませんでした…。 精進します。

3. VIPERアーキテクチャのRoutingに関してTIPS

lllllYkeillll (@lllllYkeillll) | Twitter

www.slideshare.net

V: 画面
I: ロジック
P: 仲介する
E: データ
R: どこに何があるか知ってる

VIPERの概要から入り、構成の説明、Routingについての説明、こう実装すると良いんじゃない?、これ使うと良いよ!、という話をしてくださっていました。 VIPERは勉強中で、まだまだ掴めていないので、大変勉強になりました!特に構成の説明が分かりやすかったです。 Generambaを使うのは鉄板っぽいですね。自分も使おう。 GitHub - hyperoslo/Compass: Compass helps you setup a central navigation system for your application は初めて聞きました。全部URLSchemeで取れる、という代物だそうです。ちょっとピンと来てないので勉強します…。 あとは「KickStarter iOSアプリのStoryboardのenumでの管理〜」をお勧めされていました。 これはR.swiftほどはいらないけど、文字列管理したくない、という場合ですかね?

4. kotlinコルーチンで作ってみる画像ローダ

どくぴー (@e10dokup) | Twitter

speakerdeck.com 新卒さんだそうです。 この時CAの新卒さん3名いらしてましたね。積極的。 コルーチンといえば、ゲーム会社の時(C++)に大先輩がさらっと使ってて「かっこいい…👀」となった覚えがある。 Unityでも結構お世話になりますね。 Kotlin1.1ではexperimentalなるものとして実装されているそうです。(not標準ライブラリ) async/awaitはCoroutineの機能の一部とのこと。 多用する機会はなさそうですが、使いどころありそうですね。 Rx使ってる場合、ちょっと慣れるまで混乱しそうな予感…。

5. Firebase Realtime Databaseを良さげに抽象化する

🙌🐼ひらり🐼🙌 (@hiragram) | Twitter

speakerdeck.com Firebase歴1ヶ月…!!やっぱり、すごいなぁと思う人たちはぱぱっと手を動かすなぁと改めて思いました。 抽象レイヤーを作って、ぐちゃっとならない様にする話。

tryいっぱいあるけど治安が悪いわけではないです そういえばObjectMapperの中身見たことないな、と聞いてて思いました。 こういうところもちゃんと勉強したいところ。

6. FirebaseUIとSDWebImageのコラボでFirebaseStorageの画像を表示する

K-BOY a.k.a 筋肉エンジニア (@soft_builder_k) | Twitter

qiita.com Firebase第2弾。個人アプリのクオリティがすごい。筋肉エンジニアの方。 Firebaseで画像を取得する際に、ファイルのダウンロードURLしか分からない為、いつもやる画像処理ができない。 色々調べてできました!というお話でした。 色々と懇親会とかコメントとかで「これは?」と盛り上がったのが個人的にすごく好きな流れでした。 勉強会ならではですよね。

7. Androidで動画編集アプリの技術選択

Masayuki Suda (@daasuu) | Twitter

speakerdeck.com

アプリの機能で、エンコード、動画撮影、動画再生の3つが必要になったそうです。 その際の技術選択の時の話でした。 エンコード、動画撮影に関してはMediaCodec & OpenGLESで自作し、 動画プレビューに関してはExoPlayerを選択されたとのことでした。 OpenGLESで自作って、すごいですね…👀 作成したExoPlayerFilterというライブラリに対してのPR大歓迎!とのことでしたので、得意な方いらっしゃったら是非!

8. danger-swift

pancake(Satoshi)🇮🇳 (@jpmartha_jp) | Twitter

speakerdeck.com

githubのPRチェックを自動でするものですね。 swiftlintのプラグインもあるそうです。 これは聞いてる方々でも検討を考える人が多かった印象でした。 使ってみようかなー。

9. ViewPager

hkusu (@hkusu_) | Twitter

qiita.com

アニメーションのデモが豊富でした! 「汎用的に利用できるPageTransformerを作っておくと便利」とのことで、作った上で、こういう風に使うとこういうアニメーションになるよ、と紹介してくださっていました。

10. Natural Language APIとその裏側を覗く

akatsuki174 (@akatsuki174) | Twitter

speakerdeck.com

泣く泣く縮めた発表版でない、完全版 Natural Language APIとその裏側を覗く〜完全版〜 // Speaker Deck

WWDC2017で発表された「Natural Language Processing and your Apps」のざっくりとした内容と、裏側で使われている技術について、の話でした。 こういうところで使われてるのがそれだよ、という紹介をしてくださり(全然知らなかったからありがたし)、固有表現抽出なるものを使っていると思われるので、そこを掘り下げていく、という流れで進みました。 そこから固有表現抽出の紹介をしてくださっていました。 今まで触れたことがない話だったので、完全版をしっかり読んでみたいと思います。

11. dagger2のSubComponentとdependenciesの使い分け

tsuyoyo (@tsuyogoro) | Twitter

www.slideshare.net

すごく分かりやすかったです。 SubComponentはとっつきやすいけど、親子までという制約があるのが辛み。 dependenciesは、componentの理解がきついけど、親子以上まで作れるのは大きい。

下記が実用例とのこと。 Dagger2 を活用して scope を意識した作りを実現する - Qiita

12. Getting all Enum element

廣瀬 \(^o^)/ 雄大 (@yhirose741) | Twitter

資料は見つかりませんでしたが、下記のライブラリの紹介でした。 github.com

countで取得できたり、elementsでcaseの名前が取れたり、便利そうでした。 中身読んで、スターを押す、という流れが良さそうですね!

終わり

次回は10/25にエウレカさんであるそうです!(by https://github.com/potatotips/potatotips) 公開されたら気づけますように!

リポジトリの初git pushがrejectされる

git init
からの
git remote add origin git@github.com:takattata/notification-word.git
からの
git push origin master
でいつも詰まる

> git push origin master
To github.com:takattata/notification-word.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:takattata/notification-word.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

git慣れしてない自分には投げ出したくなるエラーですが、「とにかくまずpullをするのです」という意味なのは汲めたので、pullしてみたもののうまくいかず…

結局ググってて見つけたとこのコメントに(どこのページか分からなくなりました…Qiitaだったはず…)、git pull --rebase origin masterというのを見かけたので試してみたところ解決

というのを書いている最中に、pullの仕方を間違えていたのではないかと気づきました
履歴がgit pull master originになってる
これgit pull origin masterではなかろうか

…ま、まあでも--rebaseつけてなかったら多分commitしてたものが消えてしまってたと思うので、怪我の功名とでも思っておきます

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

ブログ続かないぃ…

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

遷移しないで画面全体を更新させる為に、特定のプロパティを初期化し直したくて、プロパティ更新の為の初期化関数を作って呼び出す形にしました。
同じ処理なので、宣言時に初期化していた箇所も削除して、今回作った初期化関数を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に正式に上げられるだろうし…。 もんもん

UITableViewCellの上に乗せたUITextViewを反応させる

問題:UITableViewCellの上にUITextViewを乗っけた時、タップしてもcellが反応してくれない

    @IBOutlet weak var textView: UITextView! {
        didSet {
            textView.isUserInteractionEnabled = false
        }
    }

完璧

参照:
iphone - How to pass touch from a UITextView to a UITableViewCell - Stack Overflow

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ちゃんと勉強しよう…。
いまいちはっきりと分かってない。