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
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
110
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
6
2.4k
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
270
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
340
スマート反転とウェブアクセシビリティ
camiha
0
120
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
210
Hello, Hiroshima Geospatial Data! — Exploring DoboX with Python
ra0kley
0
170
PyO3 で既存 Python 評価器を Rust core 化する ー wasm-bindgen でブラウザにも配るための設計
kdash
1
470
PHPプロジェクトの結合バランスを可視化する #php_night
kajitack
0
220
XHTMLが残したもの
yosuke_furukawa
PRO
1
420
ハーネス設計入門 〜プロンプト、コンテキストの次〜
kinopeee
54
36k
AIエージェント時代のコードレビューを設計する
nogu66
6
2.5k
Featured
See All Featured
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
Agile that works and the tools we love
rasmusluckow
331
22k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
340
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
490
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.5k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.9k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
Discover your Explorer Soul
emna__ayadi
2
1.3k
Optimizing for Happiness
mojombo
378
71k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Skip the Path - Find Your Career Trail
mkilby
1
220
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