This article is a contribution article, one leaf (blog)
Welcome to the original article or translation to us, the way of submission: [email protected] or on the homepage click on the "Submission of explosive material"
First, solve the problem
The SWIFT project requires the use of packaged OBJECTIVE-C components and third-party libraries, and Apple offers solutions that handle most of the daily needs, but not as perfect, with many problems in the process of mixing. This article summarizes Swift-compatible objective-c issues to help you better use Swift, with the following table of contents:
1. Swift calls OBJECTIVE-C code
2. Objective-c Invoke Swift code
3. Swift compatible Xib/storyboard
4. Objective-c Smart Call to incompatible swift methods
5. Multi-target compilation error resolution
6. Third-party class library support
Second, the basic mixed programming
Swift and Objective-c's code calls each other, not as convenient as objective-c and C + +, and requires some additional configuration work. Whether Swift calls Objective-c or Objective-c calls Swift,xcode requires two steps in processing:
2.1 Swift calls OBJECTIVE-C code
Xcode calls the OBJECTIVE-C code for swift, with the exception of macro definitions, which are relatively well supported.
2.1.1 First step in using Objetvie-c
Tell Xcode, which objective-c class to use, create a new. h header file, the file name can be arbitrarily taken, it is recommended to use the "project name-bridging-header.h" command format.
Tips
Swift's iOS project, create the class file in Xcode6, by default automatically selects the file under the OS X tag, you must select the file under the iOS tag, otherwise the grammar intelligence hint will not work, and the serious result will cause the packing error.
2.1.2 The second step, target is configured so that the created header file takes effect
When you set the objective-c bridging Header , the path is configured correctly, for example: a file named "ilswift-bridging-header.h" is created, stored in the root directory of the Ilswift project folder, the following is the wording:
|
ILSwift/ILSwift-Bridging-Header.h |
Of course, in a new project, create a objective-c class directly, and Xcode will prompt you to:
Directly Select Yes, if you accidentally click the other buttons, you can follow the steps above to add step by step.
2.2 Objective-c Calling Swift code
2.2.1 Objective-c calling Swift code two steps
The first step tells Xcode which classes need to be used (automatic processing of classes that inherit from NSObject, this step is not required), and the keyword @objc (className) to mark
|
import UIKit
@objc(ILWriteBySwift)
class ILWriteBySwift {
var name: String!
class func newInstance() -> ILWriteBySwift {
return ILWriteBySwift()
}
} |
The second step introduces the header file, the Xcode header file naming rules for
|
$(SWIFT_MODULE_NAME)-Swift.h |
Examples are as follows:
|
#import "ILSwift-Swift.h" |
Tips
Unclear swift_module_name can be viewed through the following steps
2.2.2 Not found $ (swift_module_name)-swift.h
1. If you encounter this problem, follow the steps below to perform a routine check
-
OK import swift_module_name)-swift.h header file name is correct
-
Swift_module_name)-swift.h was not rebuilt after clean, executed xcode->product->build
2. header file loop
In mixed programming projects, because of the simultaneous use of both languages, the following requirements often arise: in the case of the Swift project, a class objectvie-c write is required, and the Class A uses some of the functions of Swift, the loop of the header file, which causes the compiler not to properly build the $ (swift_ module_name)-swift.h, when you encounter this problem, do the following with the. h file
|
// Delete the following header files // # import "ILSwift-Swift.h" // Import classes via code @class ILSwiftBean; |
At the top of the objevtive-c. m file, add
|
#import "ILSwift-Swift.h" |
The use of undecalared identifier error appears or the method is not found, as follows:
There are several possible reasons for this:
-
The Swift class used is not inherited from NSObject, and the keyword can be added
-
Swift_module_name)-swift.h No real-time updates, xcode->product->build
-
This swift file uses a type or syntax that is not supported by OBJECTIVE-C, such as private
There are some problems not found in the method, Xcode no Smart tip:
The type of conversion not supported by Apple's official
-
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
Third, Xib/storyboard support
Swift projects encounter two different issues when using Xib/storyboard
3.1 Xib do not load view content
When creating Uiviewcontroller, the Xib file is selected by default, and when Xib is consistent with the class file name, it can be instantiated with the following code:
|
let controller = ILViewController() |
Operation, the interface is not a thing, xib is not loaded. Workaround, precede the class with @objc (class name), for example:
|
import UIKit
@objc(ILViewController)
class ILViewController: UIViewController {
} |
Tips:
Uiviewcontroller that are created in storyboard, do not require @objc (class name) and can be kept compatible
3.2 Storyboard Cannot find a class file
The Swift language introduces the module concept and, when converted by keyword @objc (class name), causes the following two types of errors because Storboard does not update the module property in a timely manner:
3.2.1 The Swift class or Objective-c class marked with @objc (class name) may have an error:
2015-06-02 11:27:42.626 ilswift[2431:379047] Unknown class _ttc7ilswift33ilnotfindswifttagbyobjccontroller in Interface Builder file.
Workaround, press, select Blank in module, direct enter
3.2.2 Swift class with no @objc (class name) tag
|
2015-06-02 11:36:29.788 ILSwift[2719:417490] Unknown class ILNotFindSwiftController inInterface Builder file. |
Workaround, press, select the correct module
3. The cause of the above error: After setting the storyboard, directly in the class file, add or remove the @objc (class name) keyword, causing the module property in storyboard is not automatically updated, so a more general solution is that Let storyboard automatically update the module as follows:
3.3 Error Simulation Demo download
In order to be able to get a clearer understanding of the solution process, the above error has been simulated, want to try to solve the above problems of students can directly download the demo
Iv. Objective-c Smart calls to incompatible swift methods
When you invoke a method in the Swift class in Objective-c, you will encounter a situation where the corresponding method cannot be found because some swift syntax does not support the conversion, as follows:
|
import UIKit
enum HTTPState {
case Succed, Failed, NetworkError, ServerError, Others
}
class ILHTTPRequest: NSObject {
class func requestLogin(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(), { () -> Void in
callback(state: HTTPState.Succed)
})
})
}
} |
The corresponding $ (swift_module_name)-swift.h file is:
|
SWIFT_CLASS("_TtC12ILSwiftTests13ILHTTPRequest")
@interface ILHTTPRequest : NSObject
- (SWIFT_NULLABILITY(nonnull) instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end |
As can be seen from the above header file, the method Requestlogin uses the unsupported Swift enumeration, the conversion method is automatically ignored, there are two ways to skillfully solve similar problems:
4.1 Packaging with supported Swift syntax
In the swift file, add a compatible wrapper method Wraprequestlogin, note that incompatible types or syntax cannot be used in this method
import UIKit
enum HTTPState: Int {
case Succed = 0, Failed = 1, NetworkError = 2, ServerError = 3, Others = 4
}
class ILHTTPRequest: NSObject {
class func requestLogin(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(), { () -> Void in
callback(state: HTTPState.Succed)
})
})
}
class func wrapRequestLogin(userName: String, password: String, callback: (state: Int) -> (Void)) {
self.requestLogin(userName, password: password) { (state) -> (Void) in
callback(state: state.rawValue)
}
}
}
The corresponding $ (swift_module_name)-swift.h file is:
SWIFT_CLASS("_TtC12ILSwiftTests13ILHTTPRequest")
@interface ILHTTPRequest : NSObject
+ (void)wrapRequestLogin:(NSString * __nonnull)userName password:(NSString * __nonnull)password callback:(void (^ __nonnull)(NSInteger))callback;
- (SWIFT_NULLABILITY(nonnull) instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
At this point, we can use the wrapping method directly in the Objective-c Wraprequestlogin
4.2 Using Inheritance Wisely
With inheritance you can support all swift types, the primary functionality is implemented in OBJECTIVE-C, and unsupported syntax is called in the Swift file, for example, Illoginsupercontroller as the parent class
|
@interface ILLoginSuperController : UIViewController
@property (weak, nonatomic) IBOutlet UITextField *userNameField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
- (IBAction)loginButtonPressed:(id)sender;
@end
////////////////////////////////////////////////////////////////
@implementation ILLoginSuperController
- (IBAction)loginButtonPressed:(id)sender
{
}
@end |
Create Swift file, inherit from Illoginsupercontroller, call those unsupported syntax in this swift file
|
import UIKit class ILLoginController: ILLoginSuperController { override func loginButtonPressed (sender: AnyObject!) { ILHTTPRequest.requestLogin (self.userNameField.text, password: self.passwordField.text) {(state)-> (Void) in // Specific business logic } } } |
Five, multiple target compilation error resolution
There are some compilation errors when using multiple target
5.1 Use of undeclared type
This type of error is because the currently running target cannot find a file that must be compiled. Add the file to target, support ilswifttests target below, select the check box before ilswifttests
5.2 Does not has a member named
This type of error may be caused by the following two reasons, the workaround is as follows:
1. This method comes from the parent class, and the parent class file is not added to the current target
2. This method comes from the extension, and the extension is not added to the current target
Tips
If the check finds that all class files have been accurately added to target, but compiled or not, focus on checking that the bridge file is set correctly, and adding the corresponding header file to the bridge file. It is recommended that all target bridging files be directed to the same file, if not specifically requested. For the settings of the bridging file, refer to 2.1
Vi. third-party class library support
The Swift project canceled precompiled files, and some third-party objective-c libraries did not import the necessary frameworks (such as Uikit) to cause compilation errors
6.1 Cocoapods cannot find the. o File
In the Cocoapods project, some of the. o files for some class libraries are not found, leading to the following two types of errors:
-
A compilation error exists in the class library itself
-
Swift does not pre-compile, uikit, etc. not imported
Add the code file from this library file directly to the project, compile, and resolve the error.
6.2 Jsonmodel Support
Some simple features of Jsonmodel can be used in swift, and some complex data models recommend the use of Objevtive-c
|
import UIKit
@objc(ILLoginBean)
public class ILLoginBean: JSONModel {
var userAvatarURL: NSString?
var userPhone: NSString!
var uid: NSString!
} |
Tips
When Swift uses the Jsonmodel framework, the field can only be a support type in nsfoundation, and the newly added string, Int, array, and so on under swift cannot be used
6.3 Friends League statistics
The referenced from error is present in the introduction of the Friends League statistics SDK in the SWIFT project:
Workaround, find other Linker Flags, add-lz
Vii. Overview
Most mature third-party frameworks are now written using objective-c, which inevitably involves mixed programming in two languages during development, with a number of strange problems. Because the unknown has the value of exploration, Swift's simplicity and speed, can greatly advance the development progress. So from today onwards, bold start to try.
Http://www.cocoachina.com/swift/20150608/12025.html
Swift Project compatibility Objective-c issues Summary