Interoperability is a feature that enables Swift and objective-c to be combined, enabling you to use another language in a file written in one language. When you are ready to start incorporating Swift into your development process, you should know how to use interoperability to redefine and improve your program for writing COCOA applications.
The important thing about interoperability is that you are allowed to use the Objective-c API interface when writing Swift code. When you import a objective-c framework, you can instantiate its Class and interact with it using native Swift syntax.
Initialization
In order to instantiate the Objective-c Class with Swift, you should call one of its initializers using swift syntax. When the Init method of objective-c changes to Swift, they are rendered with swift initialization syntax. The "init" prefix is truncated as a keyword to indicate that the method is an initialization method. The Init method, which begins with "Initwith", is also removed. This part of the method, separated from "init" or "initwith", becomes lowercase and is treated as the parameter name of the first argument. The remainder of each part of the method name turns stale parameter name. These method names are called in parentheses.
As an example, you would do this when you use OBJECTIVE-C:
- Objective-c
- UITableView *mytableview = [[UITableView alloc]
- Initwithframe:cgrectzero style:uitableviewstylegrouped];
In Swift, you should do this:
- Swift
- Let Mytableview:uitableview = UITableView (Frame:cgrectzero, style:. Grouped)
You don't need to call Alloc,swift to handle it for you. Note that "Init" does not appear when using the Swift-style initialization function.
You can explicitly declare the type of an object at initialization time, or you can ignore it, and Swift can correctly determine the type of the object.
- Swift
- Let MyTextField = Uitextfield (frame:cgrect (0.0, 0.0, 200.0, 40.0))
The UITableView and Uitextfield objects here have the same functionality that you used in objective-c. You can use them in the same way, including accessing properties or calling methods in their own classes.
For the sake of unification and simplicity, the Objective-c factory method is also mapped in Swift as a convenient initialization method. This mapping allows them to use the same simple and straightforward initialization method. For example, in objective-c you might call a factory method like this:
- Objective-c
- Uicolor *color = [Uicolor colorwithred:0.5 green:0.0 blue:0.5 alpha:1.0];
In Swift, you should do this:
- Swift
- Let color = Uicolor (red:0.5, green:0.0, blue:0.5, alpha:1.0)
Accessing properties
When accessing and setting the properties of a Objective-c object in Swift, use the dot syntax:
- Swift
- Mytextfield.textcolor = Uicolor.darkgraycolor ()
- Mytextfield.text = "Hello World"
- If mytextfield.editing {
- Mytextfield.editing = False
- }
When the Get or set property is used directly, the property name is not appended with parentheses. Note that a pair of parentheses is appended to the Darkgraycolor, because Darkgraycolor is a class method of Uicolor, not a property.
In Objective-c, a parameterless method with a return value can be used as an implicit access function and can be called using the same method as the accessor. However, in Swift it is no longer possible to do so, only attributes declared with the @property keyword will be introduced as attributes.
Method
The point syntax is used when calling the Objective-c method in Swift.
When the Objective-c method transitions to Swift, the first part of Objective-c's selector will be the method name and appear before the parentheses, and the first parameter will appear directly in parentheses with no parameter name. The remaining parameter names are filled in parentheses, corresponding to the parameter one by one.
As an example, you would do this when you use OBJECTIVE-C:
- Objective-c
- [Mytableview Insertsubview:mysubview Atindex:2];
In Swift, you should do this:
- Swift
- Mytableview.insertsubview (Mysubview, Atindex:2)
If you call an parameterless method, you must still add a pair of parentheses after the method name
- Swift
- Mytableview.layoutifneeded ()
ID compatibility (ID compatibility)
Swift contains a protocol type called Anyobject that represents any type of object, just like an ID in objective-c. The Anyobject protocol allows you to write type-safe Swift code while maintaining the flexibility of untyped objects. Because the Anyobject protocol guarantees this security, Swift imports the ID object as a anyobject.
For example, like an ID, you can assign any other type of object to an object of type Anyobject, and you can reassign other types of objects as well.
- Swift
- var myobject:anyobject = UITableViewCell ()
- MyObject = NSDate ()
You can also not convert it to the type of a specific class when calling the Objective-c method or accessing the property. This includes methods that are marked as @objc in Objcive-c.
- Swift
- Let futuredate = Myobject.datebyaddingtimeinterval (10)
- Let Timesincenow = Myobject.timeintervalsincenow
However, because the object type of Anyobject is not known until run time, it is possible to inadvertently write unsafe code. In addition, unlike Objective-c, a run-time error is reported if you call a method or the property accessed by the Anyobject object is not declared. For example, the following code will report a unrecognized selector error at run time:
- Swift
- Myobject.characteratindex (5)
- Crash, MyObject does ' t respond to that method
However, you can use Swift's optinals feature to eliminate common errors in this objective-c, and when you invoke a Objective-c method with a Anyobject object, the call becomes an implicit expansion The behavior of optional (implicitly unwrapped optional). You can use the optional attribute to determine whether an object of type Anyobject calls the method, and, similarly, you can apply this attribute to a property.
For example, in the following code, the first and second lines of code will not be executed because the length property and the Characteratindex: method does not exist in the NSDate object. The Mylength constant is assumed to be an optional int type and is assigned a value of nil. You can also use the If-let declaration to conditionally expand the return value of the method to determine whether the object can execute the method. Just like the third line.
- Swift
- Let Mylength = Myobject.length?
- Let MyChar = Myobject.characteratindex? (5)
- If Let Fifthcharacter = Myobject.characteratindex (5) {
- println ("Found \ (fifthcharacter) at index 5")
- }
For forced type conversions in Swift, converting an object from the Anyobject type to an explicit type does not guarantee success, so it returns an optional value. And you need to check the type of the value to verify that the conversion was successful.
- Swift
- Let Userdefaults = Nsuserdefaults.standarduserdefaults ()
- Let Lastrefreshdate:anyobject? = Userdefaults.objectforkey ("Lastrefreshdate")
- If let date = Lastrefreshdate as? NSDate {
- println ("\ (date.timeintervalsincereferencedate)")
- }
Of course, if you can determine the type of the object (and determine that it is not nil), you can add the as operator to force the call.
- Swift
- Let mydate = Lastrefreshdate as NSDate
- Let timeinterval = Mydate.timeintervalsincereferencedate
Use nil
In Objective-c, a reference to an object can be a null-valued raw pointer (also nil in objective-c). In Swift, all values – including references to structs and objects – are guaranteed to be non-null. As an alternative, you will wrap this nullable value as optional type. When you need to declare a value of NULL, you need to use nil. You can learn more in optionals.
Because OBJECTIVE-C does not guarantee that the value of an object is non-null, swift, when introducing the Objective-c API, ensures that the return type and parameter type of all functions are optional, before you use the Objective-c API. You should check and ensure that the value is not empty. In some cases, you may absolutely confirm that certain OBJECTIVE-C methods or properties should never return a nil object reference. To make the object easier to use in this case, Swift uses the implicitly unwrapped Optionals method to introduce the object, implicitly unwrapped optionals contains all the security features of the optional type. In addition, you can directly access the value of an object without checking for nil. When you access this type of variable, implicitly unwrapped optional first checks to see if the value of the object does not exist and throws a run-time error if it does not exist.
Extension (Extensions)
Swift's extension is similar to the OBJECTIVE-C category. Extensions to the original classes, structs, and enumerations enrich functionality, including those defined in Objective-c. You can add extensions to your system's framework or your own type, just import the appropriate modules and ensure that the classes, structs, or enumerations you use in Objective-c have the same name.
For example, you can extend the Uibezierpath class to add a equilateral triangle to it, which simply provides the side length and starting point of the triangle.
- Swift
- Extension Uibezierpath {
- Convenience init (trianglesidelength:float, Origin:cgpoint) {
- Self.init ()
- Let squareroot = Float (sqrt (3))
- Let altitude = (squareroot * trianglesidelength)/2
- moveToPoint (Origin)
- Addlinetopoint (Cgpoint (Trianglesidelength, origin.x))
- Addlinetopoint (Cgpoint (TRIANGLESIDELENGTH/2, altitude))
- Closepath ()
- }
- }
You can also use extensions to add attributes, including properties of classes and static properties. However, these properties must be computed to be obtained, and the extension will not store properties for classes, structs, and enumerations. The following example adds an attribute called area to the CGRect class.
- Swift
- Extension CGRect {
- var area:cgfloat {
- Return width * height
- }
- }
- Let rect = CGRect (x:0.0, y:0.0, width:10.0, height:50.0)
- Let area = Rect.area
- Area:cgfloat = 500.0
You can also use extensions to add a protocol to a class without adding its subclasses. If this protocol is defined in Swift, you can add comformance to its structure or enumeration regardless of whether they are defined in objective-c or in Swift.
You cannot use extensions to override methods and properties that exist in the objective-c type.
Closures (Closures)
The blocks in objective-c will be automatically imported as a closure in Swift. For example, the following is a block variable in a objective-c:
- Objective-c
- void (^completionblock) (NSData *, nserror *) = ^ (NSData *data, Nserror *error) {/* ... */}
And it's in Swift in the form of
- Swift
- Let Completionblock: (NSData, Nserror)--Void = {data, error in/* ... */}
Swift closures are compatible with blocks in objective-c, so you can pass a swift closure to a objective-c function that takes the block as a parameter. Swift closures have a type of interoperability with functions, so you can even pass the names of Swift functions.
Closures and blocks are semantically figured but different in one place: variables can be changed directly, instead of copying variables like block. In other words, the default behavior of variables in Swift is consistent with the __block variables in objective-c.
Compare objects
There are two ways to compare objects in two Swift. First, use (= =) to determine whether the contents of two objects are the same. Second, use (= = =) to determine whether a constant or variable is an instance of the same object.
Swift and objective-c generally use = = to compare with = = = operator. The Swift = = operator provides the default implementation for objects originating from NSObject. When the = = operator is implemented, Swift invokes the IsEqual: Method defined by NSObject.
The NSObject class simply does a comparison of identities, so you need to re-implement IsEqual in your own class: methods. Because you can pass the Swift object directly to the Objective-c API, you should also implement a custom isequal for these objects: method, if you want to compare the contents of two objects, instead of just comparing whether they are derived from the same object.
As part of implementing the comparison function, make sure that the object's hash property is implemented according to the objects comparison. Further, if you want your class to be a key in the dictionary, you also need to follow the Hashable protocol and implement the Hashvalues property.
Swift type compatibility
When you define a Swift class that inherits from NSObject or other objective-c classes, these classes can be seamlessly connected to the objective-c. All the steps are done automatically by the Swift compiler, and you don't need to worry about type adaptation if you never import the Swift class in the Objective-c code. In another case, if your Swift class does not originate from the Objectve-c class and you want to be able to use it in Objecive-c code, you can use the @objc attribute described below.
@objc can make your Swift API available in objective-c. In other words, you can make them available in the Objective-c code by adding @objc to any Swift methods, classes, attributes. If your class inherits from Objective-c, the compiler will automatically help you complete this step. The compiler also adds @objc to all variables, methods, and properties, if the class itself is preceded by the @objc keyword. When you use @iboutlet, @IBAction, or @nsmanaged properties, the @objc is automatically added to the front. This keyword can also be used in target-action design patterns in objetive-c, for example, Nstimer or UIButton.
When you use the Swift API in Objective-c, the compiler basically makes a direct translation of the statement. For example, Swift API func playsong (name:string) is interpreted as-(void) Playsong: (NSString *) name. However, there is one exception: When using Swift's initialization function in objective-c, the compiler adds "Initwith" before the method and capitalizes the first argument of the original initialization function. For example, this Swift initialization function init (songname:string, artist:string will be translated to-(Instancetype) Initwithsongname: (NSString *) songname Artist: (NSString *) artist.
Swift also provides a variant of the @objc keyword, through which you can customize the name of a function that is converted in objectiv-c. For example, if the name of your Swift class contains characters that are not supported in objecytive-c, you can give objective-c a name that can be substituted. If you provide a objecytive-c name to the Swift function, remember to add (:) to the function with the parameter.
- Swift
- @objc (Squirrel)
- classбелка{
- @objc (initwithname:)
- Init (имя: String) {/*...*/}
- @objc (hidenuts:intree:)
- Funcпрячьорехи (int,вдереве:дерево) {/*...*/}
- }
When you use the @objc (< #name #>) keyword in the Swift class, this class can be used in objective-c without requiring a namespace. This keyword is also useful when migrating objecive-c code to Swift. Since the archived object stores the name of the class, you should use @objc (< #name #>) to declare the same name as the old archived class so that the old class can be unpacked by the new Swift class.
Objective-c Selector (selectors)
A objective-c selector type points to a Objective-c method name. In the Swift era, Objective-c selectors were replaced by selector structures. You can create a selector from a string, such as let Myselector:selector = "Tappedbutton:". Because the string can be automatically converted to a selector, you can pass the string directly to the method that accepts the selector.
- Swift
- Import UIKit
- Class Myviewcontroller:uiviewcontroller {
- Let MyButton = UIButton (Frame:cgrect (x:0, y:0, width:100, height:50))
- Init (nibname nibnameornil:string!, bundle nibbundleornil:nsbundle!) {
- Super.init (Nibname:nibname, Bundle:nibbundle)
- Mybutton.targetforaction ("Tappedbutton:", withsender:self)
- }
- Func Tappedbutton (sender:uibutton!) {
- println ("tapped button")
- }
- }
Note: Performselector: Methods and methods associated with calling selectors are not imported into Swift because they are unsafe.
If your Swift class inherits from the Objective-c class, all of your methods can be used as objective-c selectors. Also, if your swift class is not inherited from Objective-c, if you want to use it as a selector you need to add the @objc keyword in front of it, see Swift type compatibility for details.
Swift's interaction with the Objective-c API