Talking about the objective-c hands and Swift2

Source: Internet
Author: User

This translation is exclusively licensed to SWIFTGG

Original link: objective-c pointers and Swift 2: A Simple Guide

Original Date: 2015/08/23

Translator: Mmoaay

Proofreading: NUMBBBBB

Finalized: Shanksyang

This article was written on August 23, 2015 and is compatible with Xcode7 Beta and Swift 2

Use OBJECTIVE-C in Swift to read the C pointer in Swift

The following Objective-c method returns a int pointer, or C-term (int *) :

 @interface  Span class= "Hljs-title" >pointerbridge : nsobject  { int  count;} -(int  *) getcountptr;  @end   @implementation   Pointerbridge  -(instancetype) init {self  = [super  init]; if  (self ) {count = 23 ; } return  self ;} -(int  *) getcountptr {return  &count;}  @end  

The code above defines a PointerBridge class that contains a getCountPtr method that returns a int type memory address with a value of 23. This Int is actually count an instance, which is assigned a value of 23 in the constructor method init .

I put this code in a OBJECTIVE-C header file and import the header file into my bridge header file (xxx-bridging-header.h) so that it can be used in Swift. Then I create a named instance in Swift bridge PointerBridge and get getCountPtr() The return value of the method ...

letPointerBridge()let theInt = bridge.getCountPtr()print(theInt)print(theInt.memory)

In Xcode, hold down the Option key theInt to check the type of it you will find his Swift type is UnsafeMutablePointer<Int32> . This is a pointer to the type, not the same as the Int Int type, it is just a pointer to it.

If we run this program and execute this Swift code, we will find a theInt memory address like 0x00007f8bdb508ef8 in the command line, then we will see the memory value of the member variable output 23. The memory that the access pointer points to usually returns the object to which it is pointing, in this case the original 32 bits int (in Swift Int32 )

Now let the Objective-c class support count the set value.

 @interface pointerbridge : nsobject {    intCount;} - (int*) getcountptr;-(void) SetCount: (int) Newcount;@end @implementation pointerbridge -(instancetype) init { Self= [SuperINIT];if( Self) {count = at; }return  Self;} - (int*) Getcountptr {return&count;} - (void) SetCount: (int) Newcount {count = Newcount;}@end

We can call setCount() the method to modify count the value. Because theInt it is a pointer, it is updated by the setCount modification count theInt.memory . Do not forget that the memory address is not changed, the change is the value.

In other words, the following code prints the number 23 on the command line, and then prints the number 1000.

let bridge = PointerBridge()let theInt = bridge.getCountPtr()print(theInt.memory// 23bridge.setCount(1000)print(theInt.memory// 1000

If you want to avoid writing every time .memory , there is a shortcut to .memory assigning a variable:

let bridge = PointerBridge()let theInt = bridge.getCountPtr()let// 23

As before, the command line outputs 23. However, if we call the setCount() method modified value as before count , the problem arises:

let bridge = PointerBridge()let theInt = bridge.getCountPtr()let// 23bridge.setCount(1000// 23

The problem occurs because of a value that countVal is assigned to it. The value is 23 when the value is assigned, so countVal it has its own memory address, which permanently preserves the value of 23, so it has lost the pointer's characteristics. countValnow it's just a normal Int32 type.

Create a C pointer in Swift

What if we want to do the opposite of the above? Instead Int of using a type to count assign a value, pass in a pointer?

We assume that there is one of the following methods in the OBJECTIVE-C code:

- (void) setCountPtr:(int *)newCountPtr {    count = *newCountPtr;}

This is a very good way to do this, but it is to newCountPtr reassign the value to count, but in Swift development you do encounter scenarios where you need to pass in pointers. This is done in a way that shows you how to create a pointer type in Swift and then pass in to the Objective-c method.

You might simply think that you can pass in a value as long as you use a reference operator like & Int , just as you did in C. In objective-c you can write this:

int500;[self setCountPtr:&mcount];

This code can successfully count update the value to 500. In Swift, however, you will find it more complex (and more verbose) through auto-completion. It needs to pass UnsafeMutablePointer<Int32> in a variable of a type newCountPtr .

I know this type is disgusting, and it looks really complicated. But, in fact, it's quite simple, especially if you know the pointers in Obj-c. If you want to create an object of a UnsafeMutablePointer<Int32> type, we only need to call the constructor method, the only parameter that needs to be passed in is the size of the pointer (you should know that C's pointer is not a storage type, so it does not store the size of the information)

let bridge = PointerBridge()let theInt = bridge.getCountPtr()print(theInt.memory// 23let newIntPtr = UnsafeMutablePointer<Int32>.alloc(1)newIntPtr.memory100bridge.setCountPtr(newIntPtr)print(theInt.memory// 100

The only parameter that needs to be UnsafeMutablePointer<Int32> passed to the constructor is the number of objects that need to allocate space, so we pass in 1, because we only need one Int32 object. Then we memory can assign values to our new pointers simply by turning back on what we did before. In the end, we just need to pass the simple drip newIntPtr into the setCountrPtr method, then print out the value of the previous theInt pointer, and we'll see that its value has been updated to 100.

Summarize

UnsafeMutablePointer<T>The type of sibling type is UnsafePointer<T> fundamentally just an abstraction of the C pointer. You can think of them as an optional type of Swift, which is easier to understand. Instead of being directly equal to an exact value, they do a layer of abstraction over an exact value. Their type is generic, which allows them to use other values, not just Int32 . For example, if you need to pass in an Float object, you may need to UnsafeMutablePointer<Float> .

The point is: you're not putting a Int strong turn UnsafeMutablePointer<Int> because the pointer is not simply a Int value. So, if you need to create a new object, you need to call the constructor method UnsafeMutablePointer<Int>(count: Int) .

After this article we will continue to delve into some of the details of the function pointers, and then learn how to leverage the advantages of these features to better interact with the C and Objective-c APIs. Be sure to sign up for our Newsletter so you don't miss out on these wonderful content!

Talking about the objective-c hands and Swift2

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.