2017-05-01 40 views
1

我想訪問iOS專用功能_setApplicationIsOpaque:(僅供個人使用和測試)。無法識別的選擇器調用「_setApplicationIsOpaque:」

我已經實現了這個代碼:

@_silgen_name("_setApplicationIsOpaque:") func _setApplicationIsOpaque(_ arg1: Bool) 

let invokeSetApplicationIsOpaque: (Bool) -> Void = { 
    // The Objective-C selector for the method. 
    let selector: Selector = Selector(("_setApplicationIsOpaque:")) 
    guard case let method = class_getInstanceMethod(UIApplication.self, selector), method != nil else { 
     fatalError("Failed to look up \(selector)") 
    } 

    // Recreation of the method's implementation function. 
    typealias Prototype = @convention(c) (AnyClass, Selector, Bool) -> Void 
    let opaqueIMP = method_getImplementation(method) 
    let function = unsafeBitCast(opaqueIMP, to: Prototype.self) 

    // Capture the implemenation data in a closure that can be invoked at any time. 
    return{ arg1 in function(UIApplication.self, selector, arg1)} 
}() 

extension UIApplication { 
    func setApplicationIsOpaque(_ isOpaque: Bool) { 
     return invokeSetApplicationIsOpaque(isOpaque) 
    } 
} 

我發現這種方式來訪問私有的iOS API在下面的StackOverflow問題Access Private UIKit Function Without Using Bridging Headerthis file在GitHub上。

的問題是,在運行應用程序,我得到的錯誤

[UIApplication _setBackgroundStyle:]: unrecognized selector sent to class 0x10437f348

我發現的UIApplication in this GitHub repository iOS的私有的API的報頭。

+0

很抱歉,如果我做了一些錯誤的語言,我是意大利人。 – ale00

+0

SPOLIER:我不能讓應用程序背景透明 – ale00

回答

4
- (void)_setApplicationIsOpaque:(BOOL)arg1; 

實例方法(的UIApplication),由 初始連字符-所示。實例方法被髮送到類的實例 ,而不是類本身。

Objective-C的方法是C函數與兩個隱藏參數, 「Objective-C運行編程指南」 中比較 Messaging

It also passes the procedure two hidden arguments:

  • The receiving object
  • The selector for the method

對於實例方法, 「接收對象」 是實例到 哪個消息被髮送,在你的情況下是UIApplication實例。 (對於類方法它將是類對象)。

因此雨燕擴展方法setApplicationIsOpaque 必須通過self於封閉,而且必須爲 傳遞的第一個參數的實現方法:即_silgen_name聲明不

let invokeSetApplicationIsOpaque: (UIApplication, Bool) -> Void = { 
    // The Objective-C selector for the method. 
    let selector = Selector(("_setApplicationIsOpaque:")) 
    guard case let method = class_getInstanceMethod(UIApplication.self, selector), method != nil else { 
     fatalError("Failed to look up \(selector)") 
    } 

    // Recreation of the method's implementation function. 
    typealias Prototype = @convention(c) (UIApplication, Selector, Bool) -> Void 
    let opaqueIMP = method_getImplementation(method) 
    let function = unsafeBitCast(opaqueIMP, to: Prototype.self) 

    // Capture the implemenation data in a closure that can be invoked at any time. 
    return { (appl, arg1) in function(appl, selector, arg1)} 
}() 

extension UIApplication { 
    func setApplicationIsOpaque(_ isOpaque: Bool) { 
     return invokeSetApplicationIsOpaque(self, isOpaque) 
    } 
} 

注需要在這裏。

@_silgen_name("_setApplicationIsOpaque:") func _setApplicationIsOpaque(_ arg1: Bool) 

結合雨燕功能全局符號「_setApplicationIsOpaque」, 不存在。如果你想添加一個調用該函數

_setApplicationIsOpaque(true) 

然後構建應用程序將失敗,並鏈接錯誤:

 
Undefined symbols for architecture x86_64: "__setApplicationIsOpaque:" 
+0

感謝您的答案,它的工作原理!但是,你能更好地解釋爲什麼我不需要'_silgen_name',並且爲什麼我必須傳遞實例,而在第二個鏈接中,我發佈了它並不會傳遞UIDevice實例嗎? – ale00

+0

@ ale00:_silgen_name將Swift函數綁定到全局函數,如http://stackoverflow.com/a/35231921/1187415中的最後一個代碼示例中所述,它不綁定到類或實例方法(如上所述回答)。 - Objective-C方法是一個帶有兩個「隱式參數」的C函數:接收器和選擇器(比較例如https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ ocrtDynamicResolution.html)。對於實例方法,接收者就是實例。 –

+1

@MartinR好問題:) – JAL

相關問題