Swift Interoperability: API interaction with OBJECTIVE-C (Swift version 2.0 update)-Ready

Source: Internet
Author: User
Tags c constructor

This page contains content:

    • Initialization

    • Can fail initialization

    • Accessing properties

    • Method

    • ID compatibility (ID compatibility)

    • Null values and optional values

    • Extension (Extensions)

    • Closures (Closures)

    • Compare objects

    • Swift type compatibility

    • Dynamic distribution

    • Lightweight generics

    • Objective-c Selector (selectors)

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. Each of the remaining method names becomes the parameter name in turn. These method names are called in parentheses.

As an example, you would do this when you use OBJECTIVE-C:

UITableView *mytableview = [[UITableView alloc] Initwithframe:cgrectzero style:uitableviewstylegrouped];

In Swift, you should do this:

Let Mytableview:uitableview = UITableView (Frame:cgrectzero, style:. Grouped)

You don't need to call Alloc,swift to handle it correctly 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.

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:

Uicolor *color = [Uicolor colorwithred:0.5 green:0.0 blue:0.5 alpha:1.0];

In Swift, you should do this:

Let color = Uicolor (red:0.5, green:0.0, blue:0.5, alpha:1.0)

Can fail initialization

In Objective-c, constructors return directly to the object they initialize. In order to notify the caller that initialization failed, the Objective-c constructor returns nil. In Swift, this pattern is built into the language feature, which is known as a fail-initialized initialization. Many objective-c constructors in the IOS and OSX system frameworks are checked for initialization failure. If initialization does not fail, these objective-c constructors will be initialized with init (...). is imported, and if initialization may fail, will it be init? (...) Be imported. In our own Objective-c class and in the non-checked framework class, the constructor will be init! (...) Be imported. For example, when a picture file does not exist in the specified path, the UIImage (contentsoffile:) constructor initializes the UIImage object and fails. If the initialization succeeds, we can use an optional value binding to unpack the result that can fail to initialize.

If let image = UIImage (contentsoffile: "Myimage.png") {//Loaded the image successfully} else {//Could not load t He image}

Accessing properties

Use point syntax when accessing and setting properties for Objective-c objects in Swift

Mytextfield.textcolor = Uicolor.darkgraycolor () Mytextfield.text = "Hello World"

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 in objective-c will be introduced as attributes. Methods are imported and invoked in the method description.

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. All parts of the selector are required at the time of invocation.

As an example, you would do this when you use OBJECTIVE-C:

[Mytableview Insertsubview:mysubview Atindex:2];

In Swift, you should do this:

Mytableview.insertsubview (Mysubview, Atindex:2)

If you call an parameterless method, you must still add a pair of parentheses after the method name

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.

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 the method labeled @objc in the objective-c.

Let futuredate = Myobject.datebyaddingtimeinterval (ten) 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 will be reported if you tune a method or an accessed property Anyobject object is not declared. For example, the following code will report a unrecognized selector error at run time:

Myobject.characteratindex (5)//Crash, MyObject does ' t respond to '

However, you can use Swift's optional value 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 implicitly expanded optional value. You can use the optional value attribute to determine whether an object of type Anyobject calls the method, and again, you can apply this attribute to a property.

Note: The property accessed by Anyobject always returns an optional value.

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.

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.

Swiftlet 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.

Let mydate = lastrefreshdate as Nsdatelet timeinterval = Mydate.timeintervalsincereferencedate

Null values and optional values

In Objective-c, a reference to an object can be a raw pointer with a value of NULL (abbreviated as 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.

OBJECTIVE-C can use a null tag to set a parameter type, whether the property type or the return value type can be NULL or a nil value. Individual type declarations can use the __nullable and __nonnull annotations, and the range declarations of null values can use Ns_assume_nonnull_begin and ns_assume_nonnull_end macros. If a type does not have any null-value callout information, Swift cannot distinguish between optional and non-optional value types, and will be imported as an implicit unpacking optional value.

    • A null value type declared with __nonnull or a range macro is imported into Swift as a non-null optional value non-optional.

    • A null value type declared as an __nullable callout, imported into Swift as an optional value.

    • Types that do not have a null label declared are imported into Swift as an implicit unpacking optional value.

For example, consider the following objective-c declaration:

@property (nullable) ID nullableproperty; @property (nonnull) ID nonnullproperty; @property ID unannotatedproperty; ns_assume_nonnull_begin-(ID) returnsnonnullvalue;-(void) Takesnonnullparameter: (id) value; ns_assume_nonnull_end-(Nullable ID) returnsnullablevalue;-(void) Takesnullableparameter: (Nullable ID) value;-(ID) returnsunannotatedvalue;-(void) Takesunannotatedparameter: (id) value;

Here's how they were imported into Swift:

var Nullableproperty:anyobject?var nonnullproperty:anyobjectvar Unannotatedproperty:anyobject!func Returnsnonnullvalue (), Anyobjectfunc takesnonnullparameter (Value:anyobject) func returnsnullablevalue () Anyobject?func takesnullableparameter (value:anyobject?) Func returnsunannotatedvalue (), Anyobject!func takesunannotatedparameter (value:anyobject!)

Most objective-c system frameworks, including Foundation, have provided nullable annotations that allow you to work with values in a customary and type-safe manner.

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.

Swiftextension 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 obtained by calculation, and the extension does not add storage properties for classes, structs, enumerations. The following example adds an attribute called area to the CGRect class.

Swiftextension 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:

void (^completionblock) (NSData *, nserror *) = ^ (NSData *data, Nserror *error) {/* ... */}

And it's in Swift in the form of

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 interlinked but differ in one place: variables can be changed directly, rather than 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 create a subclass in Swift that inherits from the Objective-c class, the class and the members of the class-Properties, methods, subscripts, and constructors-are automatically available in objective-c. In some cases, you need finer-grained control over how to leak the Swift API to Objective-c. If your Swift class does not inherit from the Objective-c class, or if you want to change the interface symbol name for the OBJECTIVE-C code, you can use the @objc property. If you are using an API such as a key-value watch to dynamically replace the implementation of a method, you can also gain access to the members that are automatically distributed by the OBJECTIVE-C runtime by using the dynamic modifier.

Burst in Objective-c Swift interface

This class is automatically compatible with Objective-c when you define a Swift subclass that inherits from the NSObject class or other objective-c classes. The Swift compiler has done the work you need for this part.

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 inherit from the Objective-c class and you want to be able to use it in Objective-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 usually 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 objective-c. For example, if the name of your Swift class contains characters that are not supported in objective-c, you can give objective-c a name that can be substituted. If you want to provide a objective-c name for 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.

Request Dynamic allocation

The @objc property exposes your Swift API to the Objective-c runtime, but it does not guarantee a property, method, subscript, or constructor dynamic dispatch. By bypassing the Objective-c runtime, the Swift compiler may still devirtualize or inline member access to optimize the performance of the code. When you mark a member declaration with a dynamic modifier, access to that member is always a dynamic dispatch. Because dynamic modification declarations are dispatched using the OBJECTIVE-C runtime, they are implicitly tagged with @objc attributes.

The need for dynamic allocation is rarely necessary. However, you must use dynamic modification when you want to replace the implementation of an API at run time. For example, you can use the Objective-c run-time method method_exchangeimplementations function to replace the implementation of a method when the app is running. If the Swift compiler is inline with the implementation of the method or devirtualized access to it, the new implementation will not be used.

Lightweight generics

OBJECTIVE-C declaration types that use lightweight generic parameters, such as Nsarray,nsset and Nsdictionary, are included with the type of content they save when imported to Swift.

For example, consider the following Objective-c property declaration:

@property nsarray* dates; @property nsset* words; @property nsdictionary* cacheddata;

Following is the Swift import:

var dates: [Nsdate]var words:setvar cacheddata: [Nsurl:nsdata]

Note: In addition to the collection classes in the Foundation, Objective-c's lightweight generics are ignored by Swift. Any other type that uses lightweight generics is considered non-parametric when imported into Swift.
Objective-c Selector

The

Objective-c selector is a type that points to the Objective-c method name. In Swift, the objective-c selector is replaced by the selector structure. You can create a selector from a string, such as let Myselector:selector = "Tappedbutton:". Because string literals can be automatically converted to selectors, you can pass string literals directly to any method that accepts selectors.

import uikitclass myviewcontroller: uiviewcontroller {    let  Mybutton = uibutton (Frame: cgrect (x: 0, y: 0, width: 100, height: &NBSP;50))     override init? (Nibname nibnameornil: string?, bundle nibbundleornil: nsbundle?)  {        super.init (nibname: nibnameornil, bundle:  nibbundleornil)         mybutton.addtarget (self, action:   "Tappedbutton:",  forcontrolevents:  Touchupinside)     }    func tappedbutton (sender: UIButton!)  {        print ("Tapped button")     }     required init? (Coder: nscoder)  {        super.init (Coder: coder)     }} 

Note: Performselector: Methods and methods associated with calling selectors are not imported into Swift because they are inherently unsafe.

If your Swift class inherits from the Objective-c class, all of your methods can be used as objective-c selectors. Conversely, if your swift class is not inherited from objective-c, you need to prefix the @objc property with the selector you want to use, see Swift type compatibility for details.

Swift Interoperability: API interaction with OBJECTIVE-C (Swift version 2.0 update)-Ready

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.