Interoperability is a feature that allows Swift and objective-c to be connected, 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 the way you write 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 the native Swift syntax.
Class
To use Swift to instantiate the Objective-c Class, you should call one of its initializers using swift syntax. When Objective-c's init approach changes to Swift, they initialize the syntax rendering with Swift. The "init" prefix is truncated as a keyword to indicate that the method is an initialization method. The Init method that starts with "Initwith" will also be removed. This part of the method name, separated from "init" or "initwith", is lowercase and is treated as the parameter name of the first argument. Each remaining part of the method name turns sour on the name of the parameter. These method names are called in parentheses.
For example, you would do this when using objective-c:
Copy Code code as follows:
Objective-c
UITableView *mytableview = [[UITableView alloc]
Initwithframe:cgrectzero style:uitableviewstylegrouped];
In Swift, you should do this:
Copy Code code as follows:
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 you use the Swift-style initialization function.
You can explicitly declare the type of the object when you initialize it, or you can ignore it, and Swift can correctly determine the type of object.
Copy Code code as follows:
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 use 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, Objective-c's factory approach is also mapped to a convenient initialization method in Swift. This mapping allows them to use the same straightforward initialization method. For example, in objective-c you might call a factory method as follows:
Copy Code code as follows:
Objective-c
Uicolor *color = [Uicolor colorwithred:0.5 green:0.0 blue:0.5 alpha:1.0];
In Swift, you should do this:
Copy Code code as follows:
Swift
Let color = Uicolor (red:0.5, green:0.0, blue:0.5, alpha:1.0)
Access Properties
Use point syntax when accessing and setting properties of Objective-c objects in Swift:
Copy Code code as follows:
Swift
Mytextfield.textcolor = Uicolor.darkgraycolor ()
Mytextfield.text = "Hello World"
If mytextfield.editing {
Mytextfield.editing = False
}
The property name is used directly when a get or set property is not required to append parentheses. Note that a pair of parentheses is appended to the Darkgraycolor because Darkgraycolor is a Uicolor class method, not an attribute.
In Objective-c, a parameterless method with a return value can be used as an implicit access function and can be invoked with the same method as the accessor. However, it is no longer possible to do so in Swift, only attributes declared using the @property keyword are introduced as attributes.
Method
When calling the Objective-c method in Swift, use the dot syntax.
When the Objective-c method is converted to Swift, the first part of the Objective-c selector becomes the method name and appears in front of the parentheses, and the first argument appears directly in parentheses with no parameter name. The remaining parameter names are filled with parentheses for the one by one corresponding to the parameter.
For example, you would do this when using objective-c:
Copy Code code as follows:
Objective-c
[Mytableview Insertsubview:mysubview Atindex:2];
In Swift, you should do this:
Copy Code code as follows:
Swift
Mytableview.insertsubview (Mysubview, Atindex:2)
If you call a parameterless method, you must still add a pair of parentheses after the method name
Copy Code code as follows:
Swift
Mytableview.layoutifneeded ()
ID compatibility (ID compatibility)
Swift contains a protocol type called Anyobject that represents an object of any type, just like an ID in objective-c. The Anyobject protocol allows you to write type-safe Swift code while maintaining the flexibility of an object of no type. Because the Anyobject protocol guarantees this security, Swift imports the ID object as Anyobject.
For example, as with IDs, you can assign any other type of object to an object of type Anyobject, and you can reassign other types of objects for it as well.
Copy Code code as follows:
Swift
var myobject:anyobject = UITableViewCell ()
MyObject = NSDate ()
You can also call the Objective-c method or access the property without converting it to the type of the specific class. This includes methods that are marked as @objc in the objcive-c.
Copy Code code as follows:
Swift
Let futuredate = Myobject.datebyaddingtimeinterval (10)
Let Timesincenow = Myobject.timeintervalsincenow
However, it is possible to inadvertently write unsafe code because the Anyobject object type is not known until run time. In addition, unlike objective-c, if you invoke a method or access a property Anyobject object without a declaration, a run-time error is reported. For example, the following code will report a unrecognized selector error when it is run:
Copy Code code as follows:
Swift
Myobject.characteratindex (5)
Crash, MyObject does ' t respond to so method
However, you can eliminate common errors in this objective-c by using Swift's optinals features, and when you invoke a Objective-c method with a Anyobject object, this call will become an implicit expansion The behavior of optional (implicitly unwrapped optional). You can use the optional attribute to determine whether the object of the Anyobject type calls the method, and you can apply this attribute to the attribute.
For example, in the following code, the first and second lines of code will not be executed because the length property and the Characteratindex: The method does not exist in the NSDate object. The Mylength constant is inferred as an optional int type and is assigned to nil. You can also use the If-let declaration to conditionally expand the return value of the method to determine whether the object can perform this method. Just like the third line does.
Copy Code code as follows:
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 a 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.
Copy Code code as follows:
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 make sure it is not nil), you can add the as operator to force the call.
Copy Code code as follows:
Swift
Let mydate = Lastrefreshdate as NSDate
Let timeinterval = Mydate.timeintervalsincereferencedate
Using nil
In Objective-c, a reference to an object can be a primitive pointer with a value of NULL (also the nil in objective-c). In swift, all values-including references to structures and objects-are guaranteed to be non-null. Instead, you wrap this nullable value into the optional type. When you need to declare a value to be empty, you need to use nil. You can learn more in optionals.
Since 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 access the object's value directly without checking the nil. When you access this type of variable, implicitly unwrapped optional first checks that the value of the object does not exist, and if it does not, throws a run-time error.
Extension (Extensions)
Swift's extension is similar to the objective-c category (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 class, structure, or enumeration you use in Objective-c has the same name.
For example, you can extend the Uibezierpath class to add a equilateral to it by simply providing the edges and starting point of the triangle.
Copy Code code as follows:
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 the properties of classes and static properties). However, these properties must be computed to obtain, the extension will not be the class, the struct body, the enumeration storage properties. The following example adds an attribute called area to the CGRect class.
Copy Code code as follows:
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 overwrite methods and attributes that exist in the objective-c type.
Closure (Closures)
The blocks in objective-c is automatically imported as a closure in Swift. For example, the following is a block variable in a objective-c:
Copy Code code as follows:
Objective-c
void (^completionblock) (NSData *, nserror *) = ^ (NSData *data, Nserror *error) {/* ... */}
And it's in Swift in the form of
Copy Code code as follows:
Swift
Let Completionblock: (NSData, nserror)-> Void = {data, error in/* ... * *
Swift's closure is in harmony with the blocks in objective-c, so you can pass a swift closure to a objective-c function that takes the block as an argument. Swift closures and functions have an interoperability type, so you can even pass the name of the Swift function.
Closures and blocks semantics but differ in one place: variables can be changed directly, rather than copying variables like block. In other words, the default behavior of a variable in Swift is consistent with the __block variable in objective-c.
Compare objects
When comparing objects in two Swift, you can use two methods. First, use (= =) to determine whether the contents of two objects are the same. The second, using (= = =), determines whether a constant or variable is an instance of the same object.
Swift and objective-c generally use = = to compare with = = operator. Swift's = = operator provides a default implementation for objects originating from NSObject. When implementing the = = operator, Swift invokes the nsobject-defined isequal: method.
The NSObject class only makes an identity comparison, so you need to implement the isequal in your own class: method. Because you can directly deliver the API to Objective-c by the Swift object, you should also implement custom isequal for these objects: methods, if you want to compare the contents of two objects to one another rather than simply comparing them with the same object.
As part of the implementation comparison function, make sure that the hash property of the object is implemented according to 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 attribute.
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 of the steps are automatically done by the Swift compiler, and you don't have to worry about the type adaptation problem if you never import the Swift class in objective-c code. Alternatively, if your Swift class does not originate from the Objectve-c class and you want to use it in Objecive-c code, you can use the @objc attribute described below.
@objc allows your Swift API to be used in objective-c. In other words, you can make them available in objective-c code by adding @objc to any Swift method, class, or attribute. If your class inherits from Objective-c, the compiler will automatically help you complete this step. The compiler also adds a @objc to all variables, methods, and properties, if the class itself is preceded by a @objc keyword. When you use @iboutlet, @IBAction, or @nsmanaged properties, @objc is automatically added to the front. This keyword can also be used in target-action design patterns in objetive-c, such as Nstimer or UIButton.
When you use the Swift API in Objective-c, the compiler basically translates the statements directly. For example, Swift API func playsong (name:string) is interpreted as-(void) Playsong: (NSString *) name. However, there is one exception: when you use 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 the function converted in objectiv-c. For example, if your Swift class name contains characters that are not supported in Objecytive-c, you can provide an alternative name for objective-c. If you provide a objecytive-c name for the Swift function, remember to add (:) the function with the parameter.
Copy Code code as follows:
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 the need for a namespace. This keyword is also useful when you migrate objecive-c code to Swift. Since archived objects store 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 solved by the new Swift class.
Objective-c Selector (selectors)
A objective-c selector type points to a Objective-c method name. In Swift times, the objective-c selector was replaced by a selector structure. You can create a selector from a string, such as let Myselector:selector = "Tappedbutton:". Because strings can be automatically converted to selectors, you can pass the string directly to the method that accepts the selector.
Copy Code code as follows:
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: The Performselector: Methods and associated method of calling selectors are not imported into Swift because they are unsafe.
If your Swift class inherits from Objective-c classes, all of your methods can be used as objective-c selectors. Also, if your swift class does not inherit from Objective-c, if you want to use it as a selector you will need to add the @objc keyword in the front, please see Swift type compatibility for details.