@markheng
2018-08-02T11:00:27.000000Z
字数 2278
阅读 1706
iOS
东西太多,做一下笔记
Swift中所谓UnsafePointer,其实就是指向内存的指针,为了让一切都“安全”,所以加上了很多的限制,也提供了完成“不安全”的指针的功能的API
UnsafePointer不可以改变指针所指向的内容
该类型可以改变所指向的内容
类似于C语言,&
操作符可以取到类型的UnsafeMutablePointer,要求被&
操作的类型为var
类似于UnsafePointer,也是swift中用来处理UnsafePointer中T为Void的情况使用的。
示例代码
var a = 42
withUnsafeMutablePointer(to: &a) { $0.pointee *= 2 }
var addrIn = sockaddr_in()
// Fill sockaddr_in fields
withUnsafePointer(to: &addrIn) { ptr in
ptr.withMemoryRebound(to: sockaddr.self, capacity: 1, { ptrSockAddr in
bind(socketFd, UnsafePointer(ptrSockAddr), socklen_t(MemoryLayout<sockaddr>.size))
})
}
UnsafePoint不同类型之间相互转换,用到withMemoryRebound
函数,示例代码
var addrIn = sockaddr_in()
// Fill sockaddr_in fields
withUnsafePointer(to: &addrIn) { ptr in
ptr.withMemoryRebound(to: sockaddr.self, capacity: 1, { ptrSockAddr in
bind(socketFd, UnsafePointer(ptrSockAddr), socklen_t(MemoryLayout<sockaddr>.size))
})
}
UnsafePointer与UnsafeRawPointer相互转换,代码:
let intPtr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
let voidPtr = UnsafeRawPointer(intPtr) //directly cast from unsafepointer to unsaferawpointer
let intPtrAgain = voidPtr.assumingMemoryBound(to: Int.self)
UnsafeBufferPointer可以将UnsafePointer指向的内存按照类似于swift基础数组的方式管理(比如进行随机访问)
// in C
void generic_function(int value_type, void* value);
generic_function(VALUE_TYPE_INT, (void *)2);
struct function_data data;
generic_function(VALUE_TYPE_STRUCT, (void *)&data);
// in swift
generic_function(VALUE_TYPE_INT, UnsafeRawPointer(bitPattern: 2))
var data = function_data()
withUnsafePointer(to: &data, { generic_function(VALUE_TYPE_STRUCT, UnsafeRawPointer($0)) } )
有时候需要设置回调函数,按照通常方式设置,那么有可能被调用的对象已经被释放而导致访问错误,因此需要一个持久化的指针,代码如下
struct CallbackUserData {
func sayHello() { print("Hello world!" ) }
}
func callback(userData: UnsafeMutableRawPointer) {
let callbackUserData = Unmanaged.fromOpaque(userData).takeRetainedValue()
callbackUserData.sayHello() // "Hello world!"
}
var userData = CallbackUserData()
let reference = Unmanaged.passRetained(userData).toOpaque()
set_callback(callback, reference)
这里想要执行set_callback(),有一种情况是调用该函数结束之后,离开了作用域,导致userData被释放,从而导致回调出错,使用opaquePointer可以解决这个问题。重点在于Unmanaged对象的passRetained().toOpeque()和fromOpeque().takeRetainedValue()方法。