Ios 将闭包传递给私有API';s
我正在尝试从私有API MPAVRoutingController获取所有可用的airplay设备。我正在为swift使用一个名为performSelector swift的第三方执行选择器库。我尝试调用的方法是fetchAvailableRoutesWithCompletionHandler。这需要一个参数,即objective-c块<代码>-(void)fetchAvailableOutesWithCompletionHandler:(id/*block*/)arg1代码>当我尝试传递一个闭包时,我会得到一个编译错误,如果我没有传递任何东西,我的应用程序就会崩溃。我没有发布这个应用程序,这就是为什么我要使用privapiIos 将闭包传递给私有API';s,ios,swift,selector,iphone-privateapi,Ios,Swift,Selector,Iphone Privateapi,我正在尝试从私有API MPAVRoutingController获取所有可用的airplay设备。我正在为swift使用一个名为performSelector swift的第三方执行选择器库。我尝试调用的方法是fetchAvailableRoutesWithCompletionHandler。这需要一个参数,即objective-c块-(void)fetchAvailableOutesWithCompletionHandler:(id/*block*/)arg1当我尝试传递一个闭包时,我会得到
let MPAVRoutingController = NSClassFromString("MPAVRoutingController")! as! NSObject.Type
let routingController = MPAVRoutingController.init()
if let availableRoutes = routingController.swift_performSelector("fetchAvailableRoutesWithCompletionHandler:", withObject: {
object in
}) {
print(availableRoutes)
}
首先。。我如何找到正确的完成区块签名: 这表明它在调用完成块时将
NSMutableArray
作为参数分配给它。这是唯一的参数。你不必这样做(拆开它)。抛出异常时,可以打印签名。有时,它还会告诉您需要哪种类型的块
接下来,我对动态调用选择器的看法 最好的选择是不执行选择器。。这是一种痛苦,尤其是当调用包含多个参数时 您可以通过接口/扩展指针进行调用。。我在C++中使用这个方法(PIPL语言中的想法…COMM接口也这样做),它与Swift,ObjuleC,java一起工作。等等 创建与对象具有相同接口的协议。创建继承该协议的扩展。然后将对象实例强制转换为该扩展/接口/协议 通过接口/扩展/协议指针调用所需的任何函数
import UIKit
import MediaPlayer
@objc
protocol MPAProtocol { //Functions must be optional. That way you don't implement their body when you create the extension.
optional func availableRoutes() -> NSArray
optional func discoveryMode() -> Int
optional func fetchAvailableRoutesWithCompletionHandler(completion: (routes: NSArray) -> Void)
optional func name() -> NSString
}
extension NSObject : MPAProtocol { //Needed otherwise casting will fail!
//Do NOT implement the body of the functions from the protocol.
}
用法:
let MPAVRoutingControllerClass: NSObject.Type = NSClassFromString("MPAVRoutingController") as! NSObject.Type
let MPAVRoutingController: MPAProtocol = MPAVRoutingControllerClass.init() as MPAProtocol
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in
print(routes);
}
如果要使用桥接头而不是创建extension+协议,只需执行一个Objective-C类别:
#import <Foundation/Foundation.h>
@interface NSObject (MPAVRoutingControllerProtocol)
- (void)fetchAvailableRoutesWithCompletionHandler:(void(^)(NSArray *routes))completion;
@end
@implementation NSObject (MPAVRoutingControllerProtocol)
@end
最后,如果您可以使用协议注入,则可以更轻松地执行此操作:
func classFromString(cls: String, interface: Protocol?) -> NSObject.Type? {
guard let interface = interface else {
return NSClassFromString(cls) as? NSObject.Type
}
if let cls = NSClassFromString(cls) {
if class_conformsToProtocol(cls, interface) {
return cls as? NSObject.Type
}
if class_addProtocol(cls, interface) {
return cls as? NSObject.Type
}
}
return nil
}
func instanceFromString<T>(cls: String, interface: Protocol?) -> T? {
return classFromString(cls, interface: interface)?.init() as? T
}
@objc
protocol MPAProtocol {
optional func availableRoutes() -> NSArray
optional func discoveryMode() -> Int
optional func fetchAvailableRoutesWithCompletionHandler(completion: (routes: NSArray) -> Void)
optional func name() -> NSString
}
let MPAVRoutingController: MPAProtocol = instanceFromString("MPAVRoutingController", interface: MPAProtocol.self)!
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in
print(routes);
}
func classFromString(cls:String,interface:Protocol?)->NSObject.Type?{
guard let接口=接口else{
将NSClassFromString(cls)返回为?NSObject.Type
}
如果让cls=NSClassFromString(cls){
如果类符合协议(cls,接口){
将cls作为NSObject返回。类型
}
如果类添加协议(cls,接口){
将cls作为NSObject返回。类型
}
}
归零
}
func instanceFromString(cls:String,interface:Protocol?)->T?{
返回classFromString(cls,接口:interface)?.init()作为?T
}
@objc
协议MPA协议{
可选func availableRoutes()->NSArray
可选func discoveryMode()->Int
可选func fetchAvailableRoutesWithCompletionHandler(完成:(路由:NSArray)->Void)
可选func name()->NSString
}
让MPAVRoutingController:MPAProtocol=instanceFromString(“MPAVRoutingController”,接口:MPAProtocol.self)!
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler!(路线)
印刷(路线);
}
首先。。我如何找到正确的完成区块签名:
这表明它在调用完成块时将NSMutableArray
作为参数分配给它。这是唯一的参数。你不必这样做(拆开它)。抛出异常时,可以打印签名。有时,它还会告诉您需要哪种类型的块
接下来,我对动态调用选择器的看法 最好的选择是不执行选择器。。这是一种痛苦,尤其是当调用包含多个参数时 您可以通过接口/扩展指针进行调用。。我在C++中使用这个方法(PIPL语言中的想法…COMM接口也这样做),它与Swift,ObjuleC,java一起工作。等等 创建与对象具有相同接口的协议。创建继承该协议的扩展。然后将对象实例强制转换为该扩展/接口/协议 通过接口/扩展/协议指针调用所需的任何函数
import UIKit
import MediaPlayer
@objc
protocol MPAProtocol { //Functions must be optional. That way you don't implement their body when you create the extension.
optional func availableRoutes() -> NSArray
optional func discoveryMode() -> Int
optional func fetchAvailableRoutesWithCompletionHandler(completion: (routes: NSArray) -> Void)
optional func name() -> NSString
}
extension NSObject : MPAProtocol { //Needed otherwise casting will fail!
//Do NOT implement the body of the functions from the protocol.
}
用法:
let MPAVRoutingControllerClass: NSObject.Type = NSClassFromString("MPAVRoutingController") as! NSObject.Type
let MPAVRoutingController: MPAProtocol = MPAVRoutingControllerClass.init() as MPAProtocol
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in
print(routes);
}
如果要使用桥接头而不是创建extension+协议,只需执行一个Objective-C类别:
#import <Foundation/Foundation.h>
@interface NSObject (MPAVRoutingControllerProtocol)
- (void)fetchAvailableRoutesWithCompletionHandler:(void(^)(NSArray *routes))completion;
@end
@implementation NSObject (MPAVRoutingControllerProtocol)
@end
最后,如果您可以使用协议注入,则可以更轻松地执行此操作:
func classFromString(cls: String, interface: Protocol?) -> NSObject.Type? {
guard let interface = interface else {
return NSClassFromString(cls) as? NSObject.Type
}
if let cls = NSClassFromString(cls) {
if class_conformsToProtocol(cls, interface) {
return cls as? NSObject.Type
}
if class_addProtocol(cls, interface) {
return cls as? NSObject.Type
}
}
return nil
}
func instanceFromString<T>(cls: String, interface: Protocol?) -> T? {
return classFromString(cls, interface: interface)?.init() as? T
}
@objc
protocol MPAProtocol {
optional func availableRoutes() -> NSArray
optional func discoveryMode() -> Int
optional func fetchAvailableRoutesWithCompletionHandler(completion: (routes: NSArray) -> Void)
optional func name() -> NSString
}
let MPAVRoutingController: MPAProtocol = instanceFromString("MPAVRoutingController", interface: MPAProtocol.self)!
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in
print(routes);
}
func classFromString(cls:String,interface:Protocol?)->NSObject.Type?{
guard let接口=接口else{
将NSClassFromString(cls)返回为?NSObject.Type
}
如果让cls=NSClassFromString(cls){
如果类符合协议(cls,接口){
将cls作为NSObject返回。类型
}
如果类添加协议(cls,接口){
将cls作为NSObject返回。类型
}
}
归零
}
func instanceFromString(cls:String,interface:Protocol?)->T?{
返回classFromString(cls,接口:interface)?.init()作为?T
}
@objc
协议MPA协议{
可选func availableRoutes()->NSArray
可选func discoveryMode()->Int
可选func fetchAvailableRoutesWithCompletionHandler(完成:(路由:NSArray)->Void)
可选func name()->NSString
}
让MPAVRoutingController:MPAProtocol=instanceFromString(“MPAVRoutingController”,接口:MPAProtocol.self)!
MPAVRoutingController.fetchAvailableRoutesWithCompletionHandler!(路线)
印刷(路线);
}
您是否知道所需关闭的签名,即对象是否绝对正确?因为私有函数肯定会对某些东西使用闭包,如果它试图传递不同的参数,则会出现错误。此外,swift_performSelector是否接受对象参数的闭包?第三方库的文档对此有何评论?抱歉,我以为我粘贴了方法签名,但我粘贴了其他内容。该签名是-(void)fetchAvailableRoutesWithCompletionHandler:(id/*block*/)arg1代码>根据反向工程头文件()。至于图书馆,我可以把它扔掉