Objective-C pointer and Swift2
Use Objective-C in Swift to read the C pointer in Swift
The following Objective-C method returnsint
Pointer, or in the C term(int *)
:
@interface 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 above Code definesPointerBridge
Class, which containsgetCountPtr
Method, this method returns a value of 23int
TypeMemory Address. ThisInt
Actuallycount
In the constructorinit
Is assigned to 23.
I put this code in a Objective-C header file, and then import this header file into my bridging header file (XXX-bridging-header.h) so that it can be used in Swift. Then I create a name in Swift namedbridge
OfPointerBridge
Instance, and then obtaingetCountPtr()
Method return value...
let bridge = PointerBridge()let theInt = bridge.getCountPtr()print(theInt)print(theInt.memory)
In Xcode, press and hold the Option key and clicktheInt
Check its type and you will find that its Swift type isUnsafeMutablePointer
. This is pointingInt
Type pointer, andInt
Type is different, it just points to itPointer.
If you run this program and then execute this Swift code, we will find thattheInt
Output in the command line is similar0x00007f8bdb508ef8The memory address, and then we will seememory
The output value of the member variable is 23. The memory pointed to by the Access pointer usually returns the objects pointed to at the underlying layer. In this example, it is the original 32-bitint
(In SwiftInt32
)
Now let the Objective-C class support settingscount
.
@interface PointerBridge : NSObject { int count;}- (int *) getCountPtr;- (void) setCount:(int)newCount;@end@implementation PointerBridge- (instancetype) init { self = [super init]; if(self) { count = 23; } return self;}- (int *) getCountPtr { return &count;}- (void) setCount:(int)newCount { count = newCount;}@end
We can callsetCount()
Method To modifycount
. BecausetheInt
Is a pointer, sosetCount
Modifycount
Will also be updatedtheInt.memory
. Don't forget that the memory address will not change, but the value will change.
That is to say, the following code prints the number 23 in 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.memory
There is a shortcut.memory
Assign a value to a variable:
let bridge = PointerBridge()let theInt = bridge.getCountPtr()let countVal = theInt.memoryprint(countVal) // 23
As before, the command line outputs 23. However, if we callsetCount()
Method Modificationcount
Value, the problem occurs:
let bridge = PointerBridge()let theInt = bridge.getCountPtr()let countVal = theInt.memoryprint(countVal) // 23bridge.setCount(1000)print(countVal) // 23
The cause of the problem iscountVal
YesValue). When assigning valuesValue)Is 23, socountVal
It has its own memory address, which permanently saves the value 23, so it has lost the pointer feature.countVal
Now it's just a normalInt32
Type.
Create a C pointer in Swift
What if we want to do the opposite? Not usedInt
Typecount
Assign a value, but pass in a pointer?
Let's assume that the Objective-C Code contains the following method:
- (void) setCountPtr:(int *)newCountPtr { count = *newCountPtr;}
This method is very useful, but it is actuallynewCountPtr
Assign a value to count again, but in Swift development, you will indeed encounter such scenarios that require pointer input. This is just to show you how to create a pointer type in Swift and then pass it into the Objective-C method.
You may simply think that you can pass in a reference operator similar &Int
Value, as you did in C. In Objective-C, you can write as follows:
int mcount = 500;[self setCountPtr:&mcount];
This code can successfullycount
The value is updated to 500. However, in Swift, you will find it more complex (and lengthy) through automatic completion ). It needs to inputUnsafeMutablePointer
TypenewCountPtr
Variable.
I know this type is disgusting and it looks complicated. But in fact it is quite simple, especially when you know the pointer in Obj-C. If you want to createUnsafeMutablePointer
Type object, we only need to call the constructor method. The only parameter that needs to be passed in this constructor is the pointer size (you should know that the pointer to C is not of the storage type, so it does not store the size information)
let bridge = PointerBridge()let theInt = bridge.getCountPtr()print(theInt.memory) // 23let newIntPtr = UnsafeMutablePointer
.alloc(1)newIntPtr.memory = 100bridge.setCountPtr(newIntPtr)print(theInt.memory) // 100
UniqueUnsafeMutablePointer
The input parameter in the constructor is the number of objects that need to be allocated space, so we can pass in 1, because we only need oneInt32
Object. Then, you just needmemory
In turn, we can assign values to the newly created pointer. In the end, we only neednewIntPtr
InputsetCountrPtr
Method.theInt
When the pointer value is printed, we can see that its value has been updated to 100.
Summary
UnsafeMutablePointer
Sibling typeUnsafePointer
Basically, it is just an abstraction of the C pointer. You can think of them as optional types of Swift, which is easier to understand. They are not directly equal to an exact value, but are abstracted over an exact value. They are generic, so that they can use other values, not justInt32
. For example, you need to inputFloat
Object, you may needUnsafeMutablePointer
.
The point is:Int
Strong ConversionIsUnsafeMutablePointer
Because the pointer is not a simpleInt
Value. Therefore, to create a new object, you must call the constructor.UnsafeMutablePointer (count: Int)
.
After this article, we will continue to study some details about function pointers and learn how to use the advantages of these features to better interact with APIs of C and Objective-C. Register our Newsletter so that you will not miss these wonderful contents!