本文结合本人项目遭遇所得
新项目是swift写的,新东西用了真的戒不掉,只是和oc混编最为致命。。。
举个栗子
我们项目中因为用到了第三方的IM服务(市面上基本上所有第三方IM服务提供的库和代码也都是oc的),坑就这么来了,以下是情景:
NSString *contentStr = [layoutConfig cellContent:self.model]; // 获得类名字符串
Class clazz = NSClassFromString(contentStr); // 字符串转Class
NIMSessionMessageContentView *contentView = [[clazz alloc] initSessionMessageContentView];
NSAssert(contentView, @"can not init content view");
复制代码
解读一下,这段IM-UI库代码的作用是用model中的字符串创建contentView的类。
例如:IM-UI库中中的OC类NIMSessionLocationContentView.h
,则
contentStr = @"NIMSessionLocationContentView"
然后得到对应的clazz为NIMSessionLocationContentView
.
因为是Swift项目,以及自定义contentView类,所以便有了我们项目的Swift文件的ContentView
-> CDNetCallTipContentView
。那么问题来了,contentStr = @"CDNetCallTipContentView"
没毛病,但是clazz却为nil
。
后面查到,这种混编情况要指明命名空间!命名空间为自己项目的Target名。例如Target是CDApp。则OC文件中正确获得CDNetCallTipContentView的方式是`contentStr = @"CDApp.CDNetCallTipContentView"。
但是问题还没有完全解决!
很多朋友因为需要,项目存在多个Target(区分开发版本或者环境等原因)。例如原Target是CDApp
,开发环境的CDApp Dev
。开发环境的Target名中间有空格,这时候如果contentStr = @"CDApp Dev.CDNetCallTipContentView"
,最后clazz却是nil
。问题就出在空格上,要把空格替换成单下划线_
即contentStr = @"CDApp_Dev.CDNetCallTipContentView"
。
以下是修改后的代码:
NSString *contentStr = [layoutConfig cellContent:self.model];
Class clazz = NSClassFromString(contentStr);
if (!clazz){
NSString * nameSpace = [NSBundle mainBundle].infoDictionary[@"CFBundleName"];
contentStr = [[NSString stringWithFormat:@"%@.%@",nameSpace,contentStr] stringByReplacingOccurrencesOfString:@" " withString:@"_"]; // 空格要换成下划线
clazz = NSClassFromString(contentStr);
}
NIMSessionMessageContentView *contentView = [[clazz alloc] initSessionMessageContentView];
NSAssert(contentView, @"can not init content view");
复制代码