如何判断UIViewController是系统SDK类还是用户自定义类?
判断UIViewController是自定义类还是系统类的方案
当然有靠谱的办法实现这个需求,完全不用给现有自定义控制器加任何额外属性或方法,非常适合你的现有项目场景。下面是具体的实现思路和代码:
核心思路
系统提供的UIViewController子类(比如UITableViewController、UIAlertController这类)都属于UIKit框架的Bundle,而我们自己写的自定义控制器默认会放在项目的主Bundle里。所以通过对比类所属的Bundle标识符,就能轻松区分两者。如果需要更严谨,还可以配合系统控制器类名列表做兜底校验。
实现controllerIsUserDefined方法
基础版(适用于绝大多数场景)
这个版本利用Bundle归属判断,逻辑简洁且可靠:
@implementation Helper + (BOOL)controllerIsUserDefined:(NSString *)controllerName { // 通过类名获取对应的Class Class controllerClass = NSClassFromString(controllerName); if (!controllerClass) { return NO; } // 获取当前类所属的Bundle NSBundle *classBundle = [NSBundle bundleForClass:controllerClass]; // 获取项目的主Bundle NSBundle *mainBundle = [NSBundle mainBundle]; // 对比Bundle标识符:主Bundle里的类就是自定义类 return [classBundle.bundleIdentifier isEqualToString:mainBundle.bundleIdentifier]; } @end
进阶版(排除第三方库控制器)
如果你的项目里引入了第三方库的控制器,不想把它们当成自定义类处理,可以在基础版的基础上增加Bundle过滤:
@implementation Helper + (BOOL)controllerIsUserDefined:(NSString *)controllerName { Class controllerClass = NSClassFromString(controllerName); if (!controllerClass) { return NO; } NSBundle *classBundle = [NSBundle bundleForClass:controllerClass]; NSBundle *mainBundle = [NSBundle mainBundle]; // 仅主Bundle的类才进入下一步判断 if (![classBundle.bundleIdentifier isEqualToString:mainBundle.bundleIdentifier]) { return NO; } // 兜底:排除可能重名的系统控制器类(不推荐自己创建和系统同名的类) NSSet *systemControllerNames = [NSSet setWithObjects: @"UIViewController", @"UITableViewController", @"UINavigationController", @"UITabBarController", @"UIAlertController", @"UISplitViewController", @"UIPageViewController", @"UIActivityViewController", nil]; return ![systemControllerNames containsObject:controllerName]; } @end
使用方式
就像你之前计划的那样,在方法交换后的控制器生命周期方法里调用即可:
NSString *controllerName = NSStringFromClass([self class]); if([Helper controllerIsUserDefined:controllerName]) { // 仅针对用户自定义UIViewController类执行操作 }
这个方案完全不需要修改现有项目里的任何自定义控制器,直接集成就能生效。
内容的提问来源于stack exchange,提问作者grassyburrito
相关产品推荐
相关产品推荐

