出现Use of undecalared identifier错误或者找不到方法,如下:
引起的原因有以下几种可能:
-
使用的Swift类不是继承自NSObject,加入关键字即可
-
SWIFT_MODULE_NAME)-Swift.h没有实时更新,Xcode->Product->Build
-
此Swift文件中使用了Objective-c不支持的类型或者语法,如private
出现部分方法找不到的问题,Xcode无智能提示:
苹果官方给出的不支持转换的类型
-
Generics
-
Tuples
-
Enumerations defined in Swift
-
Structures defined in Swift
-
Top-level functions defined in Swift
-
Global variables defined in Swift
-
Typealiases defined in Swift
-
Swift-style variadics
-
Nested types
-
Curried functions
三、Xib/StoryBoard支持
Swift项目在使用Xib/StoryBoard时,会遇到两种不同的问题
-
Xib:不加载视图内容
-
Storyboard:找不到类文件
3.1 Xib不加载视图内容
在创建UIViewController时,默认选中Xib文件,在Xib与类文件名一致时,可通过以下代码实例化:
1
|
letcontroller=ILViewController()
|
运行,界面上空无一物,Xib没有被加载。解决办法,在类的前面加上@objc(类名),例如:
4
|
importUIKit
@objc(ILViewController)
classILViewController:UIViewController{
}
|
Tips:
StoryBoard中创建的UIViewController,不需要@objc(类名)也能够保持兼容
3.2 Storyboard找不到类文件
Swift语言引入了Module概念,在通过关键字@objc(类名)做转换的时候,由于Storboard没有及时更新Module属性,会导致如下两种类型错误:
3.2.1 用@objc(类名)标记的Swift类或者Objective-c类可能出现错误:
2015-06-02 11:27:42.626 ILSwift[2431:379047] Unknown class _TtC7ILSwift33ILNotFindSwiftTagByObjcController in Interface Builder file.
解决办法,按下图,选中Module中的空白,直接回车
3.2.2 无@objc(类名)标记的Swift类
1
|
2015-06-0211:36:29.788ILSwift[2719:417490]UnknownclassILNotFindSwiftController in InterfaceBuilderfile.
|
解决办法,按下图,选择正确的Module
3.产生上面错误的原因: 在设置好Storyboard后,直接在类文件中,添加或者删除@objc(类名)关键字,导致Storyboard中 Module属性没有自动更新,所以一个更通用的解决办法是,让Storyboard自动更新Module,如下:
3.3 错误模拟Demo下载
为了能够让大家更清楚的了解解决流程,将上面的错误进行了模拟,想动手尝试解决以上问题的同学可以直接下载demo
四、Objective-c巧妙调用不兼容的Swift方法
在Objective-c中调用Swift类中的方法时,由于部分Swift语法不支持转换,会遇到无法找到对应方法的情况,如下:
8
9
10
11
12
13
14
|
importUIKit
enumHTTPState{
case Succed,Failed,NetworkError,ServerError,Others
}
classILHTTPRequest:NSObject{
classfuncrequestLogin(userName:String,password:String,callback:(state:HTTPState)->(Void)){
dispatch_async(dispatch_get_global_queue(0,0),{()->Void in
NSThread.sleepForTimeInterval(3)
dispatch_async(dispatch_get_main_queue(),153)!important; background:none!important">in
callback(state:HTTPState.Succed)
})
})
}
}
|
对应的$(SWIFT_MODULE_NAME)-Swift.h文件为:
4
|
SWIFT_CLASS( "_TtC12ILSwiftTests13ILHTTPRequest" )
@interfaceILHTTPRequest:NSObject
-(SWIFT_NULLABILITY(nonnull)instancetype)initOBJC_DESIGNATED_INITIALIZER;
@end
|
从上面的头文件中可以看出,方法requestLogin使用了不支持的Swift枚举,转换时方法被自动忽略掉,有以下两种办法,可以巧妙解决类似问题:
4.1 用支持的Swift语法包装
在Swift文件中,添加一个可兼容包装方法wrapRequestLogin,注意此方法中不能使用不兼容的类型或者语法
14
15
16
17
18
19
|
importUIKit
enumHTTPState:Int{
case Succed=0,Failed=1,NetworkError=2,ServerError=3,Others=4
}
classILHTTPRequest:NSObject{
classfuncrequestLogin(userName:String,153)!important; background:none!important">in
callback(state:HTTPState.Succed)
})
})
}
classfuncwrapRequestLogin(userName:String,callback:(state:Int)->(Void)){
self.requestLogin(userName,password:password){(state)->(Void) in
callback(state:state.rawValue)
}
}
}
|
5
|
SWIFT_CLASS( "_TtC12ILSwiftTests13ILHTTPRequest" )
@interfaceILHTTPRequest:NSObject
+(void)wrapRequestLogin:(NSString*__nonnull)userNamepassword:(NSString*__nonnull)passwordcallback:(void(^__nonnull)(NSInteger))callback;
-(SWIFT_NULLABILITY(nonnull)instancetype)initOBJC_DESIGNATED_INITIALIZER;
@end
|
此时,我们可以在Objective-c中直接使用包装后的方法wrapRequestLogin
4.2 巧妙使用继承
使用继承可以支持所有的Swift类型,主要的功能在Objective-c中实现,不支持的语法在Swift文件中调用,例如,ILLoginSuperController做为父类
11
|
@interfaceILLoginSuperController:UIViewController
@property(weak,nonatomic)IBOutletUITextField*userNameField;
@property(weak,nonatomic)IBOutletUITextField*passwordField;
-(IBAction)loginButtonPressed:(id)sender;
@end
@implementationILLoginSuperController
-(IBAction)loginButtonPressed:(id)sender
{
}
@end
|
创建Swift文件,继承自ILLoginSuperController,在此Swift文件中调用那些不支持的语法
8
|
importUIKit
classILLoginController:ILLoginSuperController{
overridefuncloginButtonPressed(sender:AnyObject!){
ILHTTPRequest.requestLogin(self.userNameField.text,password:self.passwordField.text){(state)->(Void) in
}
}
}
|
五、多Target编译错误解决
在使用多Target时,会出现一些编译错误
5.1 Use of undeclared type
此类错误,是因为当前运行的Target找不到必须编译文件。将文件添加到Target即可,如下支持ILSwiftTests Target,选中ILSwiftTests前的复选框即可
5.2 does not have a member named
此类错误可能由于如下两种原因引起,解决办法同上:
1.此方法来自父类,父类文件没有加入到当前Target
2.此方法来自扩展,扩展没有加入到当前Target
如果检查发现,所有的类文件都已经准确添加到Target中,但编译还是不通过,此时着重检查桥接文件是否正确设置,是否将相应的头文件加入到了桥接文件中。如无特别要求,建议将所有Target的桥接文件全都指向同一文件。关于桥接文件的设置,请参考2.1
六、第三方类库支持
Swift项目取消了预编译文件,一些第三方Objective-c库没有导入必要框架(如UIKit)引起编译错误
6.1 Cocoapods找不到.o文件
在使用了Cocoapods项目中,会出现部分类库的.o文件找不到,导致此种错误主要是以下两种问题:
-
类库本身存在编译错误
-
Swift没有预编译,UIKit等没有导入
将此库文件中的代码文件直接加到项目中,编译,解决错误。
6.2 JSONModel支持
在Swift中可以使用JSONModel部分简单功能,一些复杂的数据模型建议使用Objevtive-c
7
|
importUIKit
@objc(ILLoginBean)
publicclassILLoginBean:JSONModel{
var userAvatarURL:NSString?
var userPhone:NSString!
var uid:NSString!
}
|
在Swift使用JSONModel框架时,字段只能是NSFoundation中的支持类型,Swift下新添加的String、Int、Array等都不能使用
6.3 友盟统计
Swift项目中引入友盟统计SDK会出现referenced from错误:
解决办法,找到Other Linker Flags,添加-lz
七、综述
现在大部分成熟的第三方框架都是使用Objective-c写的,开发时不可避免的涉及到两种语言的混合编程,期间会遇到很多奇怪的问题。因为未知才有探索的价值,Swift的简洁快速,能够极大的推进开发进度。所以从今天开始,大胆的开始尝试。 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|