是否有任何方式来模拟[NSString stringWithFormat:@“%p”,myVar],从Objective-C,在新的Swift语言?
例如:
let str = "A String"
println(" str value \(str) has address: ?")
是否有任何方式来模拟[NSString stringWithFormat:@“%p”,myVar],从Objective-C,在新的Swift语言?
例如:
let str = "A String"
println(" str value \(str) has address: ?")
当前回答
斯威夫特2
这现在是标准库的一部分:unsafeAddressOf。
/// Return an UnsafePointer to the storage used for `object`. There's
/// not much you can do with this other than use it to identify the
/// object
斯威夫特3
对于Swift 3,使用withUnsafePointer:
var str = "A String"
withUnsafePointer(to: &str) {
print(" str value \(str) has address: \($0)")
}
其他回答
获取一个对象的(堆)地址
func address<T: AnyObject>(o: T) -> Int {
return unsafeBitCast(o, Int.self)
}
class Test {}
var o = Test()
println(NSString(format: "%p", address(o))) // -> 0x7fd5c8700970
(编辑:Swift 1.2现在包含了一个类似的叫做unsafeAddressOf的函数。)
在Objective-C中,这将是[NSString stringWithFormat:@"%p", o]。
O是对实例的引用。因此,如果o被赋值给另一个变量o2, o2的返回地址将是相同的。
这并不适用于结构体(包括String)和基本类型(如Int),因为它们直接存在于堆栈上。但我们可以检索堆栈上的位置。
获取结构、内置类型或对象引用的(堆栈)地址
func address(o: UnsafePointer<Void>) -> Int {
return unsafeBitCast(o, Int.self)
}
println(NSString(format: "%p", address(&o))) // -> 0x10de02ce0
var s = "A String"
println(NSString(format: "%p", address(&s))) // -> 0x10de02ce8
var i = 55
println(NSString(format: "%p", address(&i))) // -> 0x10de02d00
在Objective-C中,这将是[NSString stringWithFormat:@"%p", &o]或[NSString stringWithFormat:@"%p", &i]。
S是结构。因此,如果s被赋值给另一个变量s2,值将被复制,s2的返回地址将不同。
它是如何组合在一起的(指针概述)
像在Objective-C中一样,有两个不同的地址与o相关。第一个是对象的位置,第二个是对象的引用(或指针)的位置。
是的,这意味着地址0x7fff5fbfe658的内容是数字0x6100000011d0,调试器可以告诉我们:
(lldb) x/g 0x7fff5fbfe658
0x7fff5fbfe658: 0x00006100000011d0
除了字符串是结构体,在内部这和(Objective-)C的工作原理是一样的。
(目前为Xcode 6.3)
引用类型:
获取引用类型的内存地址是有意义的,因为它表示标识。 ===标识运算符用于检查两个对象是否指向同一个引用。 使用ObjectIdentifier获取内存地址
代码:
class C {}
let c1 = C()
let c2 = c1
//Option 1:
print("c1 address: \(Unmanaged.passUnretained(c1).toOpaque())")
//Option 2:
let o1 = ObjectIdentifier(c1)
let o2 = ObjectIdentifier(c2)
print("o1 -> c1 = \(o1)")
print("o2 -> c2 = \(o2)")
if o1 == o2 {
print("c1 = c2")
} else {
print("c1 != c2")
}
//Output:
//c1 address: 0x000060c000005b10
//o1 -> c1 = ObjectIdentifier(0x000060c000005b10)
//o2 -> c2 = ObjectIdentifier(0x000060c000005b10)
//c1 = c2
值类型:
获取值类型的内存地址的需求并不太重要(因为它是一个值),重点将更多地放在值的相等性上。
@Drew提供的答案只能用于类类型。 @nschum提供的答案只能用于结构类型。
但是,如果使用第二种方法获取值类型为element的数组的地址。Swift会复制整个数组,因为在Swift数组是写时复制,Swift不能确保它的行为一旦它把控制权传递给C/ c++(这是通过使用&来获取地址触发)。如果你用第一个方法,它会自动把数组转换成NSArray这当然是我们不想要的。
所以我发现最简单和统一的方法是使用lldb指令帧变量-L yourVariableName。
或者你可以把他们的答案结合起来:
func address(o: UnsafePointer<Void>) {
let addr = unsafeBitCast(o, Int.self)
print(NSString(format: "%p", addr))
}
func address<T: AnyObject>(o: T) -> String{
let addr = unsafeBitCast(o, Int.self)
return NSString(format: "%p", addr) as String
}
这当然不是最快或最安全的方法。但这对我很管用。这将允许任何nsobject子类采用此属性。
public extension NSObject {
public var memoryAddress : String? {
let str = "\(self.self)".components(separatedBy: ": ")
guard str.count > 1 else { return nil }
return str[1].replacingOccurrences(of: ">", with: "")
}
}
//usage
let foo : String! = "hello"
Swift.print(foo.memoryAddress) // prints 0x100f12980
在Swift4 about Array中:
let array1 = [1,2,3]
let array2 = array1
array1.withUnsafeBufferPointer { (point) in
print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
}
array2.withUnsafeBufferPointer { (point) in
print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
}