Closed ShotaKashihara closed 4 years ago
SVProgressHUD
が開発終了しているのではないかと話題になってた
https://github.com/SVProgressHUD/SVProgressHUD
最終の更新が2019年1月。手を入れることはないと判断しているのか。それとも、開発終了なのか。
ついにLINEがダークモードをサポートした。
LINE には着せ替え機能があり、着せ替えを適用するとダークモードの恩恵を得られない。 つまり、デフォルトのテーマにしている人のみでないとダークモードが適用にならない。
ではなぜダークモードをサポートしたのか。
個人的には 「望まれている機能」説 だと考えている。
まず、寝る前(特に電気を消したベッドの中)に白い画面を観続けるのは目がチカチカするので、黒ベースの画面は目に優しい。 また、バッテリーの消費を抑えられる。夜になったら、バッテリーが減っている人が多いし、コミュニケーションが活発になる時間帯なので、バッテリーの消費が抑えられることは嬉しい。
数年後にはダークモードは(必須ではないにしても)業界標準搭載機能になるのかな…とも思ったりしました。
@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
の利点、というのが 今の所の理解。
アノテーションぽさがあるけど、どちらかというとKotlinのDelegated propertyみたいですね。
なので@SE @Foo var count: Int
みたいに複数かけない気がする
Build Configurationを変えたときにReact Nativeのデバッグができなくなったが、Podfile
1行の修正で解決した。
もともとの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.
Debug
という名前のままだと自動的に:debug
になるが、リネームしたことで:release
が使われるようになってしまった。
React Nativeは#if DEBUG
でデバッグモードを切り替えているので、React Nativeのデバッグができなくなっていた。
https://github.com/hedjirog/SwiftShogi
今年の正月はSwiftで将棋を書きました 🌄
swift test --generate-linuxmain
コマンドを利用したLinux対応この記事で紹介されているように、可読性を向上させるために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
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) }
}
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
}
}
}
}
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.
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)
SwiftUIでのMVVMを紹介出来ればなと思って作ってみました
⚠️ 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