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
Swiftとメタデータ
Search
noppefoxwolf
June 20, 2018
Technology
3
790
Swiftとメタデータ
SwiftとObjective-Cのruntime APIの比較と`wickwirew/Runtime`のプロパティ名取得実装の読み解きです。
noppefoxwolf
June 20, 2018
Tweet
Share
More Decks by noppefoxwolf
See All by noppefoxwolf
iOSの隠されたAPIを解明し、開発効率を向上させる方法/iOSDC24
noppefoxwolf
2
280
既存アプリをvisionOS対応してリリースした話/visionOS LT vol5
noppefoxwolf
0
170
UIのブラックボックスを探る/iOSDC23
noppefoxwolf
3
3.9k
CoreGraphicsでドット絵を描こう/iOSDC22
noppefoxwolf
0
2.1k
ランタイムデバッグのススメ/iOSDC21
noppefoxwolf
1
4.3k
google/mediapipe で始めるARアプリ開発/iOSDC2020
noppefoxwolf
1
1.4k
モバイルファーストなアプリを作るためにvearがしたこと/xRDCC
noppefoxwolf
0
93
ソーシャルライブサービスにおけるデジタル化粧の仕組みと実装/iOSDC19
noppefoxwolf
4
5.3k
Limited import clarification and its effect/tryswift2019
noppefoxwolf
2
1.2k
Other Decks in Technology
See All in Technology
10XにおけるData Contractの導入について: Data Contract事例共有会
10xinc
6
620
[FOSS4G 2024 Japan LT] LLMを使ってGISデータ解析を自動化したい!
nssv
1
210
Taming you application's environments
salaboy
0
190
SREが投資するAIOps ~ペアーズにおけるLLM for Developerへの取り組み~
takumiogawa
1
190
強いチームと開発生産性
onk
PRO
34
11k
TypeScript、上達の瞬間
sadnessojisan
46
13k
CysharpのOSS群から見るModern C#の現在地
neuecc
2
3.2k
Oracle Cloud Infrastructureデータベース・クラウド:各バージョンのサポート期間
oracle4engineer
PRO
28
12k
なぜ今 AI Agent なのか _近藤憲児
kenjikondobai
4
1.4k
ISUCONに強くなるかもしれない日々の過ごしかた/Findy ISUCON 2024-11-14
fujiwara3
8
870
Lexical Analysis
shigashiyama
1
150
信頼性に挑む中で拡張できる・得られる1人のスキルセットとは?
ken5scal
2
530
Featured
See All Featured
Music & Morning Musume
bryan
46
6.2k
Six Lessons from altMBA
skipperchong
27
3.5k
Docker and Python
trallard
40
3.1k
Building Your Own Lightsaber
phodgson
103
6.1k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2.1k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Building Applications with DynamoDB
mza
90
6.1k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
169
50k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.3k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
0
89
Faster Mobile Websites
deanohume
305
30k
Transcript
4XJGUͱϝλσʔλ 4XJGUѪձWPM ! !OPQQFGPYXPMG
OPQQF ! ͖ͭͶ͕͖ʂʂ " J04ΞϓϦ։ൃ 4XJGUѪձॳࢀઓ ! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
ϝλσʔλͱ ϝλใͱɺ͢ͳΘͪσʔλʹ͍ͭͯͷσʔλͱ͍͏ ҙຯͰɺ͋Δσʔλ͕ਵͯ࣋ͭͦ͠ͷσʔλࣗʹͭ ͍ͯͷՃతͳσʔλΛࢦ͢ɻʢ8JLJௐʣ ! IUUQTKBXJLJQFEJBPSHXJLJϝλσʔλ ! !OPQQFGPYXPMG
ϝλσʔλͱ ‣ Ϋϥε໊ ‣ ΫϥεͷϓϩύςΟ໊ ‣ ܧঝݩ ‣ ४ڌ͍ͯ͠Δϓϩτίϧ FUD
! !OPQQFGPYXPMG
ϝλσʔλ͕ඞཁͳ࣌ ‣ ࠓݟ͍ͯΔϏϡʔίϯτϩʔϥΛϩάʹు͖͍ͨ ‣ ΠϯελϯεΛμϯϓͯ͠อଘ͍ͨ͠ ‣ ৄࡉͰ͔Γ͍͢ΤϥʔΛද͍ࣔͨ͠ ‣ ͍͍ײ͡ͷ03.࡞Γ͍ͨͱ͔ FUD
! !OPQQFGPYXPMG
4XJGUͰϝλσʔλΛऔಘ͢ΔʹͲ͏͢Ε͍͍ʁ ! !OPQQFGPYXPMG
ͦ͏͍͑0CKFDUJWF$ͰͲ͏͍ͯͨ͠ͷ͔ʁ ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ 0CKFDUJWF$SVOUJNF"1* class_copyPropertyList(_:_:) IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPO PCKFDUJWFDDMBTT@DPQZQSPQFSUZMJTU ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ unsigned int propertyCount = 0; objc_property_t * properties =
class_copyPropertyList([self class], &propertyCount); NSMutableArray * propertyNames = [NSMutableArray array]; for (unsigned int i = 0; i < propertyCount; ++i) { objc_property_t property = properties[i]; const char * name = property_getName(property); [propertyNames addObject:[NSString stringWithUTF8String:name]]; } free(properties); NSLog(@"Names: %@", propertyNames); ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ 0CK$SVOUJNF"1*4XJGUͰ͏͜ͱ͕Ͱ͖Δɻ import ObjectiveC ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ var count: UInt32 = 0 let properties = class_copyPropertyList(MyClass.self,
&count) for i in 0..<Int(count) { let prop = properties![i] let propName = String(cString: property_getName(prop)) print(propName) } ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ 4XJGUͰDMBTT@DPQZ1SPQFSUZ-JTUΛ͏ʹ੍ݶ͕͋Δ class MyClass: NSObject { @objc var prop1 =
"" @objc var prop2 = "" } ϓϩύςΟʹ@objcΛ͚ͭΔ͜ͱʂ˞ ˞!PCKD͕ඞཁͰ͋Γɺ/40CKFDUΛܧঝ͢Δඞཁͳ͍ɻ·ͨ!PCKDΛ͚ͭΔʹDMBTTͰ͋Δඞཁ͕͋Δ ! !OPQQFGPYXPMG
!PCKDΛ͚ͣʹϓϩύ ςΟҰཡΛऔಘ͢Δํ๏ ͳ͍Ͱ͠ΐ͏͔ʜʁ ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ &ODPEBCMF class MyClass: Encodable { var prop1 = ""
var prop2 = "" } let data = try! JSONEncoder().encode(MyClass()) let json = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) print((json as! [String : Any]).keys) ‣ <QSPQ QSPQ> ! !OPQQFGPYXPMG
SFqFDUJPO let mirror = Mirror(reflecting: MyClass()) let propNames = mirror.children.compactMap({
$0.label }) ! !OPQQFGPYXPMG
0CKFDUJWF$SVOUJNF "1*ʹ૬͢Δ GSBNFXPSLແ͍ͷ͔ʜ ! !OPQQFGPYXPMG
TXJGUEPDT3VOUJNFNE 5IFpOBMSVOUJNFJOUFSGBDFJTDVSSFOUMZ BXPSLJOQSPHSFTT ͳͦ͞͏ IUUQTHJUIVCDPNBQQMFTXJGUCMPCNBTUFSEPDT3VOUJNFNE ! !OPQQFGPYXPMG
5IJSEQBSUZSVOUJNF"1* IUUQTHJUIVCDPNXJDLXJSFX3VOUJNF IUUQTHJUIVCDPN;FXP3FqFDUJPO ! !OPQQFGPYXPMG
XJDLXJSFX3VOUJNF var md = ClassMetadata(type: MyClass<Int>.self) let info = md.toTypeInfo()
info.properties.compactMap { $0.name } ! !OPQQFGPYXPMG
1SPT$POT !PCKD JOTUBODF NFUBEBUB 0CK$SVOUJNF Y P P &ODPEBCMF P
Y Y SFqFDUJPO P Y ˚ UIJSEQBSUZBQJ P P P ! !OPQQFGPYXPMG
☺ ͡Ό͋5IJSEQBSUZͷ͓͏ʙʙ ! !OPQQFGPYXPMG
3VOUJNF3FqFDUJPO Ͳ͏ͬͯϝλσʔλΛऔ ಘ͍ͯ͠Δͷ͔ʁ ! !OPQQFGPYXPMG
3VOUJNFͷॲཧ 5ZQF͕อ࣋͞Ε͍ͯΔϝϞϦΛࢀরͯ͠ϝλσʔ λΛऔಘ͍ͯ͠Δɻ ͜ΕΒΛߏମʹͯቕΊ͍͍ͯ͢Α͏ʹͨ͠ϥΠ ϒϥϦ ϝϞϦͷϨΠΞτߏυΩϡϝϯτ͕͋Δ ! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
45&1 var type: Any.Type = Kind.self let typeAsPointer = unsafeBitCast(type,
to: UnsafeMutablePointer<Int64>.self) let metadataPointer = typeAsPointer.advanced(by: -1) let metadataRawPointer = UnsafeMutableRawPointer(metadataPointer) UZQFࣗମͷϙΠϯλ͔ΒੜϙΠϯλΛऔಘ͢Δ ! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
<ิ>WBMVFXJUOFTTUBCMF ؔΛݺͼग़࣌͢ʹܦ༝͢Δςʔϒϧ 3VOUJNFͰ͜ͷαΠζॱংΛݩʹΠϯελϯεͷϝ ϞϦߏΛ࡞Γग़ͯ͠ແཧΓੜ͢Δػೳ͕͋Δ ! !OPQQFGPYXPMG
45&1 let layout = metadataRawPointer.assumingMemoryBound(to: StructMetadataLayout.self) assumingMemoryBoundͰϙΠϯλΛ .FUBEBUB-BZPVUͷߏͷϙΠϯλͱղऍ͠·͢ɻ ! !OPQQFGPYXPMG
45&1 4USVDU.FUBEBUB-BZPVUTXJGU struct StructMetadataLayout: NominalMetadataLayoutType { var valueWitnessTable: UnsafePointer<ValueWitnessTable> var
kind: Int var nominalTypeDescriptor: UnsafeMutablePointer<NominalTypeDescriptor> } ! !OPQQFGPYXPMG
45&1 structLayout.kind //1 enumLayout.kind //2 protocolLayout.kind //12 ͜ΕͰϝϞϦͷߏΛTUSVDUʹϚοϐϯά͢Δࣄ͕ग़དྷ ͨ !
!OPQQFGPYXPMG
45&1 Nominal Type Descriptorͷoffset: ͕̐field namesͳͷͰͦ͜ͷ࣮ମΛࢀর͢ΔͱɺϓϩύςΟ໊ͷ $4USJOHͷྻ͕औಘͰ͖Δɻ ! !OPQQFGPYXPMG
45&1 struct Animal { var name: String } let cString
= metadata.pointee.nominalTypeDescriptor.pointee.fieldNames.advanced() String(cString: cString) → name $4USJOHͷࢀরΛ4USJOHʹม͢ΔͱɺϓϩύςΟ໊͕ औಘͰ͖Δɻ ! !OPQQFGPYXPMG
45&1 ͋ͱ͜ͷ$4USJOHͷࢀরΛϓϩύςΟζϥͯ͠औಘ ͍͚ͯ͠ɺશͯͷϓϩύςΟ໊͕औಘͰ͖Δɻ ࣮ࡍଞͷϙΠϯλ͔ΒϓϩύςΟͷΛऔಘͯͦ͠ͷΛऔಘ͍ͯ͠Δ ! !OPQQFGPYXPMG
8BSOJOH ͜ͷํ๏વ4XJGUͷ༷มߋͰϝϞϦͷϨΠΞτ ͕มΘΔͱ͑ͳ͘ͳΔɻ 4XJGU"#*4UBCJMJUZ.BOJGFTUP IUUQTHJUIVCDPNBQQMFTXJGUCMPCNBTUFSEPDT"#*4UBCJMJUZ.BOJGFTUPNE ! !OPQQFGPYXPMG
&YBNQMFQSPKFDU IUUQTHJUIVCDPNOPQQFGPYXPMG.FUBEBUB&YBNQMF ! !OPQQFGPYXPMG
·ͱΊ ‣ ϝλσʔλʹΞΫηε͢Δํ๏ෳ͋ΓҰҰ Ͱ͋Δ ‣ ७4XJGUͳߏମͷ.FUBEBUBΛ҆શʹಘΔํ๏· ͩແ͍ɻ ‣ ϝϞϦΛࢀর͢ΔࣄͰɺ௨ৗऔಘग़དྷͳ͍ଟ͘ͷ ใʹΞΫηεͰ͖Δ
! !OPQQFGPYXPMG