Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
R.swift to Asset Symbols
Search
417.72KI
September 26, 2023
Programming
400
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
R.swift to Asset Symbols
417.72KI
September 26, 2023
More Decks by 417.72KI
See All by 417.72KI
Comparing decimals in Swift Testing
417_72ki
0
260
Reboot a personal app abandoned for 10 years with recent techs
417_72ki
0
130
iTunes・おぼえていますか〜ScriptingBridge今昔物語〜
417_72ki
1
240
The history of entry-point in iOS app Development
417_72ki
0
540
Refactor with using `available` and `deprecated`
417_72ki
3
840
CLIツールにSwift Concurrencyを適用させようとしている話
417_72ki
3
520
CI with Danger-Swift
417_72ki
1
280
Graduation from Playground beginner
417_72ki
3
1k
Trap Questions in Java and Obj-C
417_72ki
1
380
Other Decks in Programming
See All in Programming
SlackアプリとLambdaの 連携を構築した話
pawn_4_s
1
130
freeeにおけるEvalsの実践例の紹介
freee
PRO
0
130
源内ハンズオン概要編
hideg
0
190
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
520
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
340
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
19k
プロポーザルを書いてもらう
pvcresin
0
560
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
240
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
4.9k
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
5
1.6k
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.4k
How I Won Prize Money at a Hackathon Using Codex and Symphony Alpha
yasei_no_otoko
0
110
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.3k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
630
Leo the Paperboy
mayatellez
8
2.2k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Everyday Curiosity
cassininazir
0
290
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
490
Designing for Performance
lara
611
70k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
480
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
170
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
500
Deep Space Network (abreviated)
tonyrice
0
260
Transcript
4XJGUѪձWPM,PUMJOѪձWPM!,* 3TXJGU͔Β"TTFU$BUBMPH ʙ4XJGU4ZOUBYΛԊ͑ͯʙ
.FTXJGU let name = "(redacted)" let twitter = "417_72ki" let
github = "417-72KI" let company = "(redacted)" var products = [ "MockUserDefaults", "MultipartFormDataParser", "BuildConfig.swift", "SSGH", ] var contributing = [ "Danger-Swift", "octokit.swift", "etc..." ]
3TXJGUͬͯ·͔͢ʁ
3TXJGUͱ w YDPEFQSPKͷதΛղੳͯ͠ը૾YJCɺTUPSZCPBSEͳͲΛίʔυิͰ͖ΔΑ ͏ʹͯ͘͠ΕΔπʔϧ w 4XJGUొॳظ͔Β͋ΔރΕͨπʔϧ͔ͱࢥ͍͖#VJME5PPM1MVHJOʹରԠ ͍ͯͨ͠ΓࠓͰΜʹߋ৽͞Ε͍ͯΔ w IUUQTHJUIVCDPNNBDDBJO3TXJGU
՝ 9DPEFͰϏϧυʹࣦഊ͢Δ߹͕͋Δ
ݪҼ A*NBHF3FTPVSDFA͕෦Ͱੜ͞Ε͍ͯΔ
ݪҼ A*NBHF3FTPVSDFA͕෦Ͱੜ͞Ε͍ͯΔ
(FOFSBUFE"TTFU4ZNCPMTTXJGU 🤔
9DPEFͷ"TTFU4ZNCPMT ग़యIUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOYDPEFSFMFBTFOPUFTYDPEFSFMFBTFOPUFT
9DPEFͷ"TTFU4ZNCPMT ҙ w Ϧιʔε໊શͯDBNFM$BTFʹม͞ΕΔ w ม͞Εͨ݁Ռඃͬͨ߹ແࢹ͞ΕΔϦιʔε͕ൃੜ͢Δ
ҙ w Ϧιʔε໊શͯDBNFM$BTFʹม͞ΕΔ w ม͞Εͨ݁Ռඃͬͨ߹ແࢹ͞ΕΔϦιʔε͕ൃੜ͢Δ
ରԠࡦ "TTFU4ZNCPMTͷࣗಈੜΛແޮʹ͢Δ A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ 3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ
ରԠࡦ "TTFU4ZNCPMTͷࣗಈੜΛແޮʹ͢Δ
ରԠࡦ "TTFU4ZNCPMTͷࣗಈੜΛແޮʹ͢Δ A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ 3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ
ରԠࡦ A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ import SwiftUI import RswiftResources struct Item { var
image: ImageResource } struct ItemView: View { var item: Item var body: some View { VStack { Image(item.image) } } } #if DEBUG struct ItemView_Previews: PreviewProvider { static var previews: some View { Group { ItemView(item: .init(image: R.image.foo)) // Cannot convert value of type } } } #endif
ରԠࡦ A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ import SwiftUI import RswiftResources struct Item { var
image: RswiftResources.ImageResource } struct ItemView: View { var item: Item var body: some View { VStack { Image(item.image) } } } #if DEBUG struct ItemView_Previews: PreviewProvider { static var previews: some View { Group { ItemView(item: .init(image: R.image.foo)) // no error } } } #endif
ରԠࡦ "TTFU4ZNCPMTͷࣗಈੜΛແޮʹ͢Δ A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ 3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ
ରԠࡦ 3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ import SwiftUI import RswiftResources struct Item { var
image: ImageResource } struct ItemView: View { var item: Item var body: some View { VStack { Image(item.image) } } } #if DEBUG struct ItemView_Previews: PreviewProvider { static var previews: some View { Group { ItemView(item: .init(image: R.image.foo)) // Cannot convert value of type } } } #endif
ରԠࡦ 3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ import SwiftUI import RswiftResources struct Item { var
image: ImageResource } struct ItemView: View { var item: Item var body: some View { VStack { Image(item.image) } } } #if DEBUG struct ItemView_Previews: PreviewProvider { static var previews: some View { Group { ItemView(item: .init(image: .foo)) // no error } } } #endif
ରԠࡦ 3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ import SwiftUI struct Item { var image: ImageResource
} struct ItemView: View { var item: Item var body: some View { VStack { Image(item.image) } } } #if DEBUG struct ItemView_Previews: PreviewProvider { static var previews: some View { Group { ItemView(item: .init(image: .foo)) // no error } } } #endif
؆୯ΜɺΤϥʔҎ֎ม͑ͨΖ ʌ AЧ ů
ΜͳΘ͚͋Δ͔͍ bшb㱬ኯˑ Ч ůŰƅŖƃ
3TXJGUͰݺͼग़ͤΔόϦΤʔγϣϯ // Image(UIKit) R.image.foo() UIImage(resource: R.image.foo) // Image(SwiftUI) Image(R.image.foo) Image(uiImage:
R.image.foo()!) Image(uiImage: UIImage(resource: R.image.foo)!) // Color(UIKit) R.color.primary() UIColor(resource: R.color.primary) //Color(SwiftUI) Color(R.color.primary) Color(uiColor: R.color.primary()!) Color(uiColor: UIColor(resource: R.color.primary)!)
͜ΕΛݸݸݟͯॻ͖͑Δͱ͔ ʌůɾ㱼ɾA ŷžŷž ਖ਼نදݱͰؤு͍͍͚ͬͯͲ
ͦ͜Ͱ
4XJGU4ZOUBY
4XJGU4ZOUBY w 4XJGUίʔυͷߏจղੳɺݕࠪɺੜɺม͕Ͱ͖Δ"QQMFͷϥΠϒϥϦ w IUUQTHJUIVCDPNBQQMFTXJGUTZOUBY w ؛͞Μͷ͋Γ͕͍͓ͨ w IUUQTTQFBLFSEFDLDPNLJTIJLBXBLBUTVNJNBTUFSJOHTXJGUTZOUBY
4XJGU4ZOUBYͰΓ͍ͨ͜ͱ w 3JNBHFGPP 6**NBHF SFTPVSDF3JNBHFGPP Λ 6**NBHF SFTPVSDFGPP ʹม͢Δ w
*NBHF 3JNBHFGPP Λ*NBHF GPP ʹม͢Δ w 3DPMPSGPP 6*$PMPS SFTPVSDF3DPMPSGPP Λ 6*$PMPS SFTPVSDFGPP ʹม͢Δ w $PMPS 3DPMPSGPP Λ$PMPS GPP ʹม͢Δ
Δ͜ͱ w ύλʔϯຖʹରԠͨ͠มॲཧΛ࣮͢Δ w 3JNBHFGPP 6**NBHF SFTPVSDFGPP w 3JNBHFGPP
6**NBHF SFTPVSDFGPP w 6**NBHF SFTPVSDF3JNBHFGPP 6**NBHF SFTPVSDFGPP w 6**NBHF SFTPVSDF3JNBHFGPP 6**NBHF SFTPVSDFGPP w *NBHF 3JNBHFGPP *NBHF GPP w *NBHF VJ*NBHF3JNBHFGPP *NBHF GPP w *NBHF VJ*NBHF6**NBHF SFTPVSDF3JNBHFGPP *NBHF GPP
Δ͜ͱ w ύλʔϯຖʹରԠͨ͠มॲཧ3FXSJUFSΛ࣮ͯ͠࠶ؼతʹݺͼग़͢ w 3JNBHFGPP 3JNBHFGPP 6**NBHF SFTPVSDFGPP w
6**NBHF SFTPVSDF3JNBHFGPP 6**NBHF SFTPVSDF3JNBHFGPP 6**NBHF SFTPVSDFGPP w *NBHF 3JNBHFGPP *NBHF GPP w *NBHF VJ*NBHF3JNBHFGPP *NBHF VJ*NBHF6**NBHF SFTPVSDF 3JNBHFGPP *NBHF GPP
3JNBHFGPP 6**NBHF SFTPVSDFGPP final class RswiftResourceRewriter: SyntaxRewriter { private let
rewritableAssets = [ "image": "UIImage", "color": "UIColor" ] override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax { if let base = node.calledExpression.as(MemberAccessExprSyntax.self), let expr = visit(base).as(MemberAccessExprSyntax.self), base != expr, let assetType = base.base?.as(MemberAccessExprSyntax.self)?.declName.baseName.text, let convertedType = rewritableAssets[assetType] { // return `UIImage(resource: .expr)` or `UIColor(resource: .expr)` syntax } }
3JNBHFGPP 6**NBHF SFTPVSDFGPP 3JNBHFGPPGPP override func visit(_ node: MemberAccessExprSyntax) ->
ExprSyntax { if let base = node.base?.as(MemberAccessExprSyntax.self), base.base?.as(DeclReferenceExprSyntax.self)?.baseName.text == "R" { let resourceName = node.declName.baseName.text if rewritableAssets.keys.contains(base.declName.baseName.text) { return ExprSyntax( MemberAccessExprSyntax( leadingTrivia: node.leadingTrivia, period: .periodToken(), name: .identifier(resourceName.camelized), trailingTrivia: node.trailingTrivia ) ) } } return super.visit(node) }
3JNBHFGPP 6**NBHF SFTPVSDFGPP 3JNBHFGPP 3JNBHFGPP override func visit(_ token: ForceUnwrapExprSyntax)
-> ExprSyntax { if let expr = token.expression.as(FunctionCallExprSyntax.self), let converted = visit(expr).as(FunctionCallExprSyntax.self), expr != converted { return ExprSyntax(converted) } return super.visit(token) }
6**NBHFΛม final class UIImageRewriter: SyntaxRewriter { private let typeName =
"UIImage" override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax { if case typeName = node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text, let argument = node.arguments.first, argument.label?.text == "resource" { let newArgument = rswiftResourceRewriter.visit(argument) return ExprSyntax(node.with(\.arguments, [newArgument])) } if let member = node.calledExpression.as(MemberAccessExprSyntax.self), case "init" = member.declName.baseName.text, let argument = node.arguments.first, argument.label?.text == "resource" { let newArgument = rswiftResourceRewriter.visit(argument) return ExprSyntax(node.with(\.arguments, [newArgument])) } return super.visit(node) }
6**NBHFΛม 6**NBHF SFTPVSDF3JNBHFGPP 6**NBHF SFTPVSDFGPP final class UIImageRewriter: SyntaxRewriter {
private let typeName = "UIImage" override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax { if case typeName = node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text, let argument = node.arguments.first, argument.label?.text == "resource" { let newArgument = rswiftResourceRewriter.visit(argument) return ExprSyntax(node.with(\.arguments, [newArgument])) } if let member = node.calledExpression.as(MemberAccessExprSyntax.self), case "init" = member.declName.baseName.text, let argument = node.arguments.first, argument.label?.text == "resource" { let newArgument = rswiftResourceRewriter.visit(argument) return ExprSyntax(node.with(\.arguments, [newArgument])) } return super.visit(node) }
6**NBHFΛม JOJU SFTPVSDF3JNBHFGPP 6**NBHF SFTPVSDFGPP final class UIImageRewriter: SyntaxRewriter {
private let typeName = "UIImage" override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax { if case typeName = node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text, let argument = node.arguments.first, argument.label?.text == "resource" { let newArgument = rswiftResourceRewriter.visit(argument) return ExprSyntax(node.with(\.arguments, [newArgument])) } if let member = node.calledExpression.as(MemberAccessExprSyntax.self), case "init" = member.declName.baseName.text, let argument = node.arguments.first, argument.label?.text == "resource" { let newArgument = rswiftResourceRewriter.visit(argument) return ExprSyntax(node.with(\.arguments, [newArgument])) } return super.visit(node) }
3"$$POWFSUFS w 3TXJGUUP"TTFU$BUBMPH w IUUQTHJUIVCDPN,*3"$$POWFSUFS
%FNP
·ͱΊ w 3TXJGUͷ"1*ͱ9DPEFͷ"TTFU4ZNCPMT͕$PO fl JDU͢Δ w 4XJGU4ZOUBYΛͬͯ3JNBHF̋̋Λ"TTFU4ZNCPMTʹมͰ͖Δ w શ3TXJGUʹ·ͩ՝͕͋Δ w
"TTFU4ZNCPMT͕9*#4UPSZCPBSE%BUB"TTFUTʹରԠ͍ͯ͠ͳ͍
ελʔ͍ͩ͘͞ ҙ༁ɿUIY