wantedly / ios_night

Let's talk about iOS development -- iOS Night 📱🌙 You might apply to this meetup from
https://www.wantedly.com/companies/wantedly/projects
18 stars 0 forks source link

2020/01/07 19:30~20:30 #81

Closed ShotaKashihara closed 4 years ago

ShotaKashihara commented 4 years ago

⚠️ This repository is public. / 公開リポジトリです。

Why

Where

Pearl Jam (Subject to change)

5F, MG Shirokanedai Building (Wantedly, Inc. Tokyo HQ)

Who

You are working for Wantedly? Sure, you can join anytime. If not, you need to contact us first. Or, you can "want to visit" the meetup, which you can find in www.wantedly.com/companies/wantedly/projects.

What

You write topics like below contents and we talk about these on the meetup. Every participant needs to write one topic at least.

Also, you can find new topics from the newsletters:

How

         ・・・

参加者は開催までに話したいことを少なくとも1トピックをコメントしましょう。 ネタ被りを避けるために、まずはタイトルだけでコメントすることを推奨します。 より多くの学びを得るためにどんな内容でもアウトプットを歓迎します!😊

cc/ @wantedly/ios

Edit this template

Previous issue

https://github.com/wantedly/ios_night/issues/80

hiranodept commented 4 years ago

SwiftUI online playground

すごいの作ってる

スクリーンショット 2020-01-07 12 01 01

https://swiftui-playground.kishikawakatsumi.com/

(Runしてみたけど遅い…)

takashings commented 4 years ago

SVProgressHUD の開発終了…?

SVProgressHUDが開発終了しているのではないかと話題になってた https://github.com/SVProgressHUD/SVProgressHUD

最終の更新が2019年1月。手を入れることはないと判断しているのか。それとも、開発終了なのか。

takashings commented 4 years ago

LINE App support Dark Mode

ついにLINEがダークモードをサポートした。

個人的考察

LINE には着せ替え機能があり、着せ替えを適用するとダークモードの恩恵を得られない。 つまり、デフォルトのテーマにしている人のみでないとダークモードが適用にならない。

ではなぜダークモードをサポートしたのか。

個人的には 「望まれている機能」説 だと考えている。

まず、寝る前(特に電気を消したベッドの中)に白い画面を観続けるのは目がチカチカするので、黒ベースの画面は目に優しい。 また、バッテリーの消費を抑えられる。夜になったら、バッテリーが減っている人が多いし、コミュニケーションが活発になる時間帯なので、バッテリーの消費が抑えられることは嬉しい。

数年後にはダークモードは(必須ではないにしても)業界標準搭載機能になるのかな…とも思ったりしました。

ShotaKashihara commented 4 years ago

@propertyWrapper 実装方法メモ

ここにへぇボタンがあります。

struct へぇボタン {
    var count: Int = 0
}

ただしこのへぇボタンは実装がないので叩いても「へぇ」が出ません。 そこで var count: Int を increment したら「へぇ」が出るようにしたいですね。イメージは以下。

struct へぇボタン {
    @SE var count: Int = 0
}

var button = へぇボタン()
button.count = 1 // print("1 へぇ")
button.count = 2 // print("2 へぇ")
button.count = 3 // print("3 へぇ")

@SE (Sound Effect) というアノテーションが登場しました。 これが Swift 5.1 で登場した @propertyWrapper と呼ばれるものです。 @propertyWrapper の最小実装を見てみましょう。

@propertyWrapper
struct Hoge<T> {
    private var _wrappedValue: T
    var wrappedValue: T {
        get {
            return _wrappedValue
        }
        set {
            _wrappedValue = newValue
        }
    }
}

_wrappedValue: 値を保持するための stored property。 wrappedValue: 値へのアクセサを担う computed property。 @propertyWrapper を付ける場合、wrappedValue プロパティは実装が必須になっています。

これをもとに @SE propertyWrapper を作るとこうなりました。

@propertyWrapper
struct SE {
    private var _wrappedValue: Int = 0
    var wrappedValue: Int {
        get {
            return _wrappedValue
        }
        set {
            print("\(newValue)へぇ")
            _wrappedValue = newValue
        }
    }
}

set アクセサで print("\(newValue) へぇ") が追加されている以外はほとんど内容が変わってないです。 この propertyWrapper @SE を、 へぇボタンの var count: Int に適用すると完成です。

@propertyWrapper
struct SE {
    private var _wrappedValue: Int = 0
    var wrappedValue: Int {
        get {
            return _wrappedValue
        }
        set {
            print("\(newValue) へぇ")
            _wrappedValue = newValue
        }
    }
}

struct へぇボタン {
    @SE var count: Int
}

var button = へぇボタン()

button.count = 1 // print("1 へぇ")
button.count = 2 // print("1 へぇ")
button.count = 3 // print("1 へぇ")
button.count = 4 // print("1 へぇ")

つまるところ、 @propertyWrapper は get-set アクセサの糖衣構文であるとも言える。

struct へぇボタン {
    var count: Int = 0 {
        get {
            return value
        }
        set {
            print("\(newValue) へぇ")
            value = newValue
        }
    }
}

この get-set 部分を切り出して共通で使えることが @propertyWrapper の利点、というのが 今の所の理解。

kubode commented 4 years ago

アノテーションぽさがあるけど、どちらかというとKotlinのDelegated propertyみたいですね。 なので@SE @Foo var count: Intみたいに複数かけない気がする

kubode commented 4 years ago

React Nativeのデバッグができなくなった問題の解決策

Build Configurationを変えたときにReact Nativeのデバッグができなくなったが、Podfile1行の修正で解決した。 もともとのConfigurationがDebugだったけど、途中で別の名前にリネームしたのが原因。

https://guides.cocoapods.org/syntax/podfile.html#project

build_configurationsHash{String => symbol}

A hash where the keys are the name of the build configurations in your Xcode project and the values are Symbols that specify if the configuration should be based on the :debug or :release configuration. If no explicit mapping is specified for a configuration in your project, it will default to :release.

https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/installer/analyzer/target_inspector.rb#L123

Debugという名前のままだと自動的に:debugになるが、リネームしたことで:releaseが使われるようになってしまった。 React Nativeは#if DEBUGでデバッグモードを切り替えているので、React Nativeのデバッグができなくなっていた。

jiro commented 4 years ago

書き初め

https://github.com/hedjirog/SwiftShogi

今年の正月はSwiftで将棋を書きました 🌄

jiro commented 4 years ago

extensionを利用したメソッドのグループ化

この記事で紹介されているように、可読性を向上させるためにprivate関数をextensionでまとめる手法がある。 Using Swift Extensions The “Wrong” Way

さらに徹底してextensionを活用しているOSSを見付けたので紹介。 https://github.com/JohnSundell/Publish

大体こんな感じ。

/// 構造体の説明
public struct Hoge {
    /// プロパティの説明
    var foo: Foo
}

public extension Hoge {
    /// 関数の説明
    func bar() {}
}

internal extension Hoge {
    func baz() {}
}

private extension Hoge {
    func qux() {}
}

e.g. https://github.com/JohnSundell/Publish/blob/master/Sources/Publish/API/Section.swift

ngtk commented 4 years ago

Turning Property Wrappers into Function Wrappers

https://medium.com/flawless-app-stories/turning-property-wrappers-into-function-wrappers-2be3a49229f5

Use case

In this use case, we can make the cached function by using @Cached property wrapper.

struct Trigo {
    @Cached static var cachedCos = { (x: Double) in cos(x) }
}

Property Wrapper definition

It caches the input and output values as a dictionary.

@propertyWrapper
struct Cached<Input: Hashable, Output> {

    private var cachedFunction: (Input) -> Output

    init(wrappedValue: @escaping (Input) -> Output) {
        self.cachedFunction = Cached.addCachingLogic(to: wrappedValue)
    }

    var wrappedValue: (Input) -> Output {
        get { return self.cachedFunction }
        set { self.cachedFunction = Cached.addCachingLogic(to: newValue) }
    }

    private static func addCachingLogic(to function: @escaping (Input) -> Output) -> (Input) -> Output {
        var cache: [Input: Output] = [:]

        return { input in
            if let cachedOutput = cache[input] {
                return cachedOutput
            } else {
                let output = function(input)
                cache[input] = output
                return output
            }
        }
    }
}

Conclusion

In this article, we took the example of implementing a caching mechanism, but we could cover many more use cases: for instance, we could implement wrappers like @Delayed(delay: 0.3) and @Debounced(delay: 0.3), to deal with the timing of code execution. Or we could provide thread safety via a wrapper @ThreadSafe, that would wrap the execution of a piece of code around a Lock.

ngtk commented 4 years ago

Localization in SwiftUI

https://swiftwithmajid.com/2019/10/16/localization-in-swiftui/

LocalizedStringKey is a special struct which is provided by the SwiftUI framework. It conforms ExpressibleByStringLiteral protocol, which allows us to create this struct by using a String value. Text component, on the other hand, has an overload that accepts LocalizedStringKey instead of String. It allows us to use our localization keys in a very transparent way. Let’s take a look at a quick example.

let goal: LocalizedStringKey = "goal"
let text = Text(goal)
sorakoro commented 4 years ago

ポケモン図鑑をMVVMで作った話し (未完成)

SwiftUIでのMVVMを紹介出来ればなと思って作ってみました