Share
Embed
Transcript
53 slides
-
How to access hidden iOS APIs and enhance development efficacy.
2024/08/23 10:50ʙ Track B Regular talkʢ20 minʣ 1/53 -
noppe • Indie app developer • DAWN for mastodon •
vear - VTuber camera app 2/53 -
DeNA Co., Ltd., • 2016 ~ • Pococha • iOS
Senior App Developer • Code de Crossword at DeNA booth • They are sponsoring my talk 3/53 -
Enjoy my talk! • The talk will be in Japanese
• Slides are in English 4/53 -
ObjC Private API Sample *object = [Sample new]; // Success
[object send]; // Error [object validate]; 10/53 -
ObjC Private API You can expose the method by adding
a header file yourself. @interface Sample (Private) - (BOOL)validate; @end // Success [objcect validate]; 11/53 -
ObjC Private API You can call the method by using
performSelector without adding a header file. [object performSelector:NSSelectorFromString(@"validate")]; 12/53 -
Swift Hidden API • Swift does not have any header
file. • Dynamic Link Framework has Swift module data. 14/53 -
Swift Hidden API • tbd file • dynamic library stub
for Eager linking 4 • public and internal api list • swiftinterface file • public api list 4 https://developer.apple.com/jp/videos/play/wwdc2022/110364/ 15/53 -
Swift Hidden API /Applications /Xcode.app /Contents /Developer /Platforms /iPhoneSimulator.platform /Developer
/SDKs /iPhoneSimulator.sdk /System /Library /Frameworks /SwiftUI.framework 16/53 -
Swift Hidden API SwiftUI.framework ├── Headers │ ├── SwiftUI.h │
└── SwiftUI_Metal.h ├── Modules │ ├── SwiftUI.swiftmodule │ │ ├── arm64-apple-ios-simulator.swiftdoc │ │ ├── arm64-apple-ios-simulator.swiftinterface │ │ ├── x86_64-apple-ios-simulator.swiftdoc │ │ └── x86_64-apple-ios-simulator.swiftinterface │ └── module.modulemap └── SwiftUI.tbd 17/53 -
Swift Hidden API arm64-apple-ios-simulator.swiftinterface ... @_Concurrency.MainActor open class UIHostingController<Content> :
UIKit.UIViewController where Content : SwiftUICore.View { @_Concurrency.MainActor @preconcurrency public var _disableSafeArea: Swift.Bool { get set } } ... 18/53 -
Swift Hidden API SwiftUI.tbd --- !tapi-tbd tbd-version: 0 targets: [
i386-ios-simulator, x86_64-ios-simulator, arm64-ios-simulator ] install-name: '/System/Library/Frameworks/SwiftUI.framework/SwiftUI' current-version: 0.0.0 swift-abi-version: 0 exports: - targets: [ i386-ios-simulator, x86_64-ios-simulator, arm64-ios-simulator ] symbols: [ ... ] 20/53 -
Swift Hidden API SwiftUI.tbd (exports/symbols) ... '_$s7SwiftUI4ViewPAAE12userActivity...', '_$s7SwiftUI4ViewPAAE12userActivity...', '_$s7SwiftUI4ViewPAAE12userActivity...', '_$s7SwiftUI4ViewPAAE12userActivity...',
'_$s7SwiftUI4ViewPAAE12variableBlur...', '_$s7SwiftUI4ViewPAAE12variableBlur...', ... 21/53 -
Swift Hidden API swift demangle '_$s7SwiftUI4....' _$s7SwiftUI4.... ---> View.variableBlur(maxRadius: CGFloat,
mask: Image, opaque: Bool) -> some 22/53 -
Swift Hidden API modify swiftinterface file yourself @available(iOS 17.0, macOS
14.0, watchOS 10.0, tvOS 17.0, *) extension SwiftUICore.View { nonisolated public func variableBlur( maxRadius: CoreFoundation.CGFloat, mask: SwiftUI.Image, opaque: Swift.Bool ) -> some SwiftUI.View } 23/53 -
UnderscoredAttributes1 5 extension View { @_disfavoredOverload func badge(_ count: Int)
-> some View { // ... } } 5 https://github.com/swiftlang/swift/pull/37854 1 https://github.com/swiftlang/swift/blob/main/docs/ReferenceGuides/UnderscoredAttributes.md 25/53 -
Hidden API's risk ⚠ • Semantics are subject to change.
• Side-effects are not controllable. • AppStore rejection • Uncompliance in review guildeline 2.5.12 2 https://developer.apple.com/jp/app-store/review/guidelines/ 27/53 -
Lowering risk • Testing for lowing changing and side-effects risk.
func testPrivateMethod() { let object = Sample() let selector = #Selector("setUserName:") object.performSelector(selector, withObject: "noppe") #expect(object.userName == "noppe") if !object.responds(selector) { fatalError("Selector not found") } } 28/53 -
What's the best usecase? Development Phase Suitable Concept Development !
Testing ⾠ Product Development " 30/53 -
Concept Development • Concept Development, Hackathon, UI Design, and more.
• Troublesome implementation • Difficult implementation • Complex visual effect 31/53 -
UITextView.setAttributedPlaceholder:8 extension UITextView { func setPlaceholder(_ placeholder: String?) { let
string = placeholder.map(NSAttributedString.init) let selector = Selector(("setAttributedPlaceholder:")) if responds(to: selector) { perform(selector, with: string) } } } 8 https://gist.github.com/AdamWhitcroft/c6ffc0323b9ce227588df7145685ae26#file-wrappeduitextview-swift-L41 32/53 -
UINavigationItem._setWeeTitle:7 extension UINavigationItem { func setWeeTitle(_ title: String) { let
selector = Selector(("_setWeeTitle:")) if responds(to: selector) { perform(selector, with: title as NSString) } } } 7 https://github.com/feedback-assistant/reports/issues/506 34/53 -
Testing UIDebuggingInformationOverla y • iOS10 • easy to use •
iOS11+ • needs to jump through some hoops 38/53 -
Product Development Using hidden API is risky. But, You can
learn API design from hidden APIs. 40/53 -
API naming You can learn API naming rules from official
SDK headers. -(void)_endScrollingCursorOverrideIfNecessary; -(UIOffset)_firstPageOffset; -(id)_frameLayoutGuideIfExists; (note) Don't override the method names, because ObjC uses Dynamic Dispatch. 41/53 -
API design You can learn UI scructures and architectures. @interface
UITextView : UIScrollView { _UITextContainerView* _containerView; ... } ... @end 42/53 -
How to find hidden APIs? • Read swiftinterface, tbd and
headers. • Get method name list • Read the stacktrace • Find SNS posts • Send feedback to Apple 43/53 -
Get method name list _methodDescription (located in UIKitCore) import UIKit
let selector = Selector("_methodDescription") let names = scrollView.perform(selector) print(names) 44/53 -
Get method name list • Runtime Header • p-x9/swift-objc-dump9 9
https://github.com/p-x9/swift-objc-dump 45/53 -
Send feedback to Apple • Apple sometimes publicizes the API
after receiving our feedback. • Write feedback about usecases and APIs. 49/53 -
Thank you • Special thanks • @p_x9 • Guilherme Rosado
Martins 52/53