[关闭]
@markheng 2018-08-02T03:00:27.000000Z 字数 2278 阅读 1558

swift指针 - UnsafeWorld of Swift 3.0

iOS


原网址:
http://technology.meronapps.com/2016/09/27/swift-3-0-unsafe-world-2/?utm_source=tuicool&utm_medium=referral

东西太多,做一下笔记

Swift中所谓UnsafePointer,其实就是指向内存的指针,为了让一切都“安全”,所以加上了很多的限制,也提供了完成“不安全”的指针的功能的API

UnsafePointer

UnsafePointer不可以改变指针所指向的内容

UnsafeMutablePointer

该类型可以改变所指向的内容
类似于C语言,&操作符可以取到类型的UnsafeMutablePointer,要求被&操作的类型为var

UnsafeRawPointer

类似于UnsafePointer,也是swift中用来处理UnsafePointer中T为Void的情况使用的。

withUnsafeMutablePointer

示例代码

  1. var a = 42
  2. withUnsafeMutablePointer(to: &a) { $0.pointee *= 2 }
  1. var addrIn = sockaddr_in()
  2. // Fill sockaddr_in fields 
  3. withUnsafePointer(to: &addrIn) { ptr in
  4.     ptr.withMemoryRebound(to: sockaddr.self, capacity: 1, { ptrSockAddr in
  5.         bind(socketFd, UnsafePointer(ptrSockAddr), socklen_t(MemoryLayout<sockaddr>.size))
  6.     })
  7. }

指针间相互转换

UnsafePoint不同类型之间相互转换,用到withMemoryRebound函数,示例代码

  1. var addrIn = sockaddr_in()
  2. // Fill sockaddr_in fields 
  3. withUnsafePointer(to: &addrIn) { ptr in
  4.     ptr.withMemoryRebound(to: sockaddr.self, capacity: 1, { ptrSockAddr in
  5.         bind(socketFd, UnsafePointer(ptrSockAddr), socklen_t(MemoryLayout<sockaddr>.size))
  6.     })
  7. }

UnsafePointer与UnsafeRawPointer相互转换,代码:

  1. let intPtr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
  2. let voidPtr = UnsafeRawPointer(intPtr) //directly cast from unsafepointer to unsaferawpointer
  3. let intPtrAgain = voidPtr.assumingMemoryBound(to: Int.self)

UnsafeBufferPointer

UnsafeBufferPointer可以将UnsafePointer指向的内存按照类似于swift基础数组的方式管理(比如进行随机访问)

bitPattern

  1. // in C
  2. void generic_function(int value_type, void* value);
  3.  
  4. generic_function(VALUE_TYPE_INT, (void *)2);
  5. struct function_data data;
  6. generic_function(VALUE_TYPE_STRUCT, (void *)&data);
  7. // in swift
  8. generic_function(VALUE_TYPE_INT, UnsafeRawPointer(bitPattern: 2))
  9. var data = function_data()
  10. withUnsafePointer(to: &data, { generic_function(VALUE_TYPE_STRUCT, UnsafeRawPointer($0)) } )

Opaque Pointer

有时候需要设置回调函数,按照通常方式设置,那么有可能被调用的对象已经被释放而导致访问错误,因此需要一个持久化的指针,代码如下

  1. struct CallbackUserData {
  2.     func sayHello() { print("Hello world!" ) }
  3. }
  4.  
  5. func callback(userData: UnsafeMutableRawPointer) {
  6.     let callbackUserData = Unmanaged.fromOpaque(userData).takeRetainedValue()
  7.  
  8.     callbackUserData.sayHello() // "Hello world!" 
  9. }
  10.  
  11. var userData = CallbackUserData()
  12. let reference = Unmanaged.passRetained(userData).toOpaque()
  13. set_callback(callback, reference)

这里想要执行set_callback(),有一种情况是调用该函数结束之后,离开了作用域,导致userData被释放,从而导致回调出错,使用opaquePointer可以解决这个问题。重点在于Unmanaged对象的passRetained().toOpeque()和fromOpeque().takeRetainedValue()方法。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注