The Power of Key paths in Swift
きっかけ
模型を作る時、key path
を知りました.
keyPathを変数として使えるかどうか考えている最中に、この文章を読んで整理してみました.
私がしたい変数の一つは.struct Zoo {
let animal: String
let age: Int
}
もしあれば、Zoo
のage
のpropertyを変数として使いたいです.
もし、もしlet agePathOfZooStruct = Zoo.age
よろしければ.keymappingとも言える...これまでやってきたルールのないまとまりのないモデルの組み合わせは、ハードコーディングを1つずつ行うことなく変数に加えることができます...このような考えは私にKeypathを理解させた.
まだ解決策は見つかっていませんが、次の文章は面白いです.
KeyPath?
Key paths essentially let us reference any instance property as a separate value.
As such, they can be passed around, used in expressions, and enable a piece of code to get or set a property without actually knowing which exact property its working with.
KeyPathsを使用して、instanceプロパティを個別の値として参照します.
したがって、実際にどのプロパティが機能するか分からない場合でも、コードを渡して式に使用し、propertyをインポートまたは設定できます.
キーパスには3つの主要な変異体があります.
struct Zoo {
let animal: String
let age: Int
}
let agePathOfZooStruct = Zoo.age
Key paths essentially let us reference any instance property as a separate value.
As such, they can be passed around, used in expressions, and enable a piece of code to get or set a property without actually knowing which exact property its working with.
KeyPathsを使用して、instanceプロパティを個別の値として参照します.
したがって、実際にどのプロパティが機能するか分からない場合でも、コードを渡して式に使用し、propertyをインポートまたは設定できます.
キーパスには3つの主要な変異体があります.
Keypath:propertyは読み取り専用アクセスを提供します.
WritableKeyPath:可変属性と読み書きアクセスを提供します.
ReferenceWritableKeyPath:クラスインスタンスなどの参照タイプとのみ使用できます.次に、可変属性にreadwrite accessを提供します.
(他のキーパスタイプは、内部コードの重複を減らし、タイプを削除するのに役立ちますが、主なタイプについて重点的に説明します.)
Functional shorthands Article
というモデルがあります.struct Article {
let id: UUID
let source: URL
let title: Stirng
let body: String
}
Article
モデルからidやsourceのように1つの値だけを抽出したい場合は、map
を使用します.// articles = array of Article model
let articleIDs = articles.map { $0.id }
let articleSources = articles.map { $0.source }
SWIFT 5.2以前にkeypathを使用するために、以下の拡張シーケンスが使用されていました.// Earlier Swift 5.2
extension Sequence {
func map<T>(_ keyPath: KeyPath<Element, T>) -> [T] {
return map { $0[keyPath: keyPath] }
}
}
let articleIDs = articles.map(\.id)
let articleSources = articles.map(\.source)
Sorting
extension Sequence {
func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>) -> [Element] {
return sorted { a, b in
return a[keyPath: keyPath] < b[keyPath: keyPath]
}
}
}
ということで.articles.sorted(by: \.title)
これで昇順に並びました.
No instance required
The true power of key paths comes from the fact that they let us reference a property without having to associate it with any specific instance.
(キーパスの真の力は、特定のインスタンスに関連付けずにpropertyを参照できるという事実から来ています.)struct SongCellConfigurator {
func configure(_ cell: UITableViewCell, for song: Song) {
cell.textLabel?.text = song.name
cell.detailTextLabel?.text = song.artistName
cell.imageView?.image = song.albumArtwork
}
}
上記のコードには問題はありませんが、他のモデルも同様の方法でレンダリングされる可能性があります(多くのテーブルビューユニットで表されるモデルにかかわらず、タイトル、サブタイトル、画像をレンダリングする傾向があります).そこで、プライマリパスの機能を使用して共有プロファイル実装を作成できるかどうかを見てみましょう.struct CellConfigurator<Model> {
let titleKeyPath: KeyPath<Model, String>
let subtitleKeyPath: KeyPath<Model, String>
let imageKeyPath: KeyPath<Model, UIImage?>
func configure(_ cell: UITableViewCell, for model: Model) {
cell.textLabel?.text = model[keyPath: titleKeyPath]
cell.detailTextLabel?.text = model[keyPath: subtitleKeyPath]
cell.imageView?.image = model[keyPath: imageKeyPath]
}
}
-> Usage let songCellConfigurator = CellConfigurator<Song>(
titleKeyPath: \.name,
subtitleKeyPath: \.artistName,
imageKeyPath: \.albumArtwork
)
let playlistCellConfigurator = CellConfigurator<PlayList>(
titleKeyPath: \.title,
subtitleKeyPath: \.authorName,
imageKeyPathL \.artwork
)
Converting to functions class ListViewController {
private var items = [Items]() { didSet { render() } }
func loadItems() {
loader.load { [weak self] items in
self?.items = items
}
}
func setter<Object: AnyObject, Value>(
for object: Object,
keyPath: ReferenceWritableKeyPath<Object, Value>
) -> (Value) -> Void {
return { [weak object] value in
object?[keyPath: keyPath] = value
}
}
Let't see if key paths again can help us make the above syntax a bit simpler, and if we also can get rid of that weak self
dance we so often have to do(and with it - the risk of accidentally introducing retain cycle if we forget to capture a weak reference to self
).class ListViewController {
private var items = [Item]() { didSet { render() } }
func loadItems() {
loader.load(then: setter(for: self, keyPath: \.items))
}
}
この文章は次の文章を読んで記録します.
https://www.swiftbysundell.com/articles/the-power-of-key-paths-in-swift/
Reference
この問題について(The Power of Key paths in Swift), 我々は、より多くの情報をここで見つけました
https://velog.io/@heunb/The-Power-of-Key-paths-in-Swift
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
struct Article {
let id: UUID
let source: URL
let title: Stirng
let body: String
}
// articles = array of Article model
let articleIDs = articles.map { $0.id }
let articleSources = articles.map { $0.source }
// Earlier Swift 5.2
extension Sequence {
func map<T>(_ keyPath: KeyPath<Element, T>) -> [T] {
return map { $0[keyPath: keyPath] }
}
}
let articleIDs = articles.map(\.id)
let articleSources = articles.map(\.source)
extension Sequence {
func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>) -> [Element] {
return sorted { a, b in
return a[keyPath: keyPath] < b[keyPath: keyPath]
}
}
}
articles.sorted(by: \.title)
The true power of key paths comes from the fact that they let us reference a property without having to associate it with any specific instance.
(キーパスの真の力は、特定のインスタンスに関連付けずにpropertyを参照できるという事実から来ています.)
struct SongCellConfigurator {
func configure(_ cell: UITableViewCell, for song: Song) {
cell.textLabel?.text = song.name
cell.detailTextLabel?.text = song.artistName
cell.imageView?.image = song.albumArtwork
}
}
上記のコードには問題はありませんが、他のモデルも同様の方法でレンダリングされる可能性があります(多くのテーブルビューユニットで表されるモデルにかかわらず、タイトル、サブタイトル、画像をレンダリングする傾向があります).そこで、プライマリパスの機能を使用して共有プロファイル実装を作成できるかどうかを見てみましょう.struct CellConfigurator<Model> {
let titleKeyPath: KeyPath<Model, String>
let subtitleKeyPath: KeyPath<Model, String>
let imageKeyPath: KeyPath<Model, UIImage?>
func configure(_ cell: UITableViewCell, for model: Model) {
cell.textLabel?.text = model[keyPath: titleKeyPath]
cell.detailTextLabel?.text = model[keyPath: subtitleKeyPath]
cell.imageView?.image = model[keyPath: imageKeyPath]
}
}
-> Usage let songCellConfigurator = CellConfigurator<Song>(
titleKeyPath: \.name,
subtitleKeyPath: \.artistName,
imageKeyPath: \.albumArtwork
)
let playlistCellConfigurator = CellConfigurator<PlayList>(
titleKeyPath: \.title,
subtitleKeyPath: \.authorName,
imageKeyPathL \.artwork
)
Converting to functions class ListViewController {
private var items = [Items]() { didSet { render() } }
func loadItems() {
loader.load { [weak self] items in
self?.items = items
}
}
func setter<Object: AnyObject, Value>(
for object: Object,
keyPath: ReferenceWritableKeyPath<Object, Value>
) -> (Value) -> Void {
return { [weak object] value in
object?[keyPath: keyPath] = value
}
}
Let't see if key paths again can help us make the above syntax a bit simpler, and if we also can get rid of that weak self
dance we so often have to do(and with it - the risk of accidentally introducing retain cycle if we forget to capture a weak reference to self
).class ListViewController {
private var items = [Item]() { didSet { render() } }
func loadItems() {
loader.load(then: setter(for: self, keyPath: \.items))
}
}
この文章は次の文章を読んで記録します.
https://www.swiftbysundell.com/articles/the-power-of-key-paths-in-swift/
Reference
この問題について(The Power of Key paths in Swift), 我々は、より多くの情報をここで見つけました
https://velog.io/@heunb/The-Power-of-Key-paths-in-Swift
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
class ListViewController {
private var items = [Items]() { didSet { render() } }
func loadItems() {
loader.load { [weak self] items in
self?.items = items
}
}
func setter<Object: AnyObject, Value>(
for object: Object,
keyPath: ReferenceWritableKeyPath<Object, Value>
) -> (Value) -> Void {
return { [weak object] value in
object?[keyPath: keyPath] = value
}
}
class ListViewController {
private var items = [Item]() { didSet { render() } }
func loadItems() {
loader.load(then: setter(for: self, keyPath: \.items))
}
}
Reference
この問題について(The Power of Key paths in Swift), 我々は、より多くの情報をここで見つけました https://velog.io/@heunb/The-Power-of-Key-paths-in-Swiftテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol