相信码农们都听说过反射这个词,今天要说的iOS下的反射使用方法。虽然在Object-C和Swift中都使用NSClassFromString这个方法,但是在使用过程中还是有细微的差别。具体看下面的代码注释吧
- Object-C中使用
Class urlClass = NSClassFromString(controllerValue); //controllerValue为待反射的类名
id toController = [[urlClass alloc] initWithNibName:controllerValue bundle:nil];
if ([toController isKindOfClass:[BaseViewController class]]) {
UIViewController *currentController = [self getCurrentViewController];
((BaseViewController *)toController).pushNotification = self.pushNotice;
[currentController.navigationController pushViewController:toController animated:YES];
}
Object-C中NSClassFromString调用时传入的参数就是直接的类名,相信在Object-C中使用过该方法的人,都会用,非常简单- Swift中使用
if let appName: String = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String {
let classStringName: String = String(format: "%@.%@", appName, controllerName) //此处多加了一个app的名字
if let toClass: UIViewController.Type = NSClassFromString(classStringName) as? UIViewController.Type {
let toController: UIViewController = toClass.init(nibName: controllerName, bundle: nil)
self.navigationController?.pushViewController(toController, animated: true)
}
}
Swift中NSClassFromString调用时,在类名前增加了App的名字,有点像Java中反射调用时的包路径吧(我猜其实就是)- 未搞明白的问题
Swift中直接在AppDelegate这个类中调用NSClassFromString就不需要加App名,个人猜测难道是在根路径下不用加?如有搞明白的请告知,谢谢!附上代码为证
let toClass: UIViewController.Type? = NSClassFromString(controllerValue!) as? UIViewController.Type
if toClass != nil {
let currentController: UIViewController = self.getCurrentViewController()
let toController: UIViewController = toClass!.init(nibName: controllerValue!, bundle: nil)
currentController.navigationController?.pushViewController(toController, animated: true)
}
补充一下,最近在拿这个反射功能时,发现在iOS版本低于9时,如果使用xib布局,加载时,会出现异想不到的问题,必须使用明确的写法,如:
var toController: UIViewController?
switch self.toControllerName! {
case "MessageListViewController":
toController = MessageListViewController(nibName: "MessageListViewController", bundle: nil)
break
case "ServiceCardViewController":
toController = ServiceCardViewController(nibName: "ServiceCardViewController", bundle: nil)
break
default:
break
}
所以让我更加确信,iOS9在工程文件管理这块有类Java中的包概念,而9以下版本没有此概念,因此上面这样的写法在iOS9中可以使用,而iOS9以下不适用。需要进一步找到方法,待找到更合适的方法,我会持续更新此文