在Swift中打印变量的内存地址

240

在新的Swift语言中,是否有任何方式可以模拟Objective-C中的[NSString stringWithFormat:@"%p", myVar]

例如:

let str = "A String"
println(" str value \(str) has address: ?")

2
[NSString stringWithFormat:@"%p", myVar] 中,myVar 必须是一个指针。在您的 Swift 代码中,str 不是一个指针,因此该比较不适用。 - user102008
8
值得注意的是,在我写这篇文章时,上述两条评论是不正确的。 - Ky -
15个回答

7
@Drew提供的答案只适用于类类型。
@nschum提供的答案只适用于结构体类型。
然而,如果您使用第二种方法来获取具有值类型元素的数组的地址。Swift将复制整个数组,因为在Swift中,数组是按写入进行复制的,并且一旦它将控制权交给C / C ++(这是通过使用&触发的),Swift无法确保它以这种方式运行。如果您改为使用第一种方法,则会自动将Array转换为NSArray,这显然不是我们想要的。
因此,我发现最简单和统一的方法是使用lldb指令frame variable -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
}

4
其他答案都不错,但我正在寻找一种将指针地址作为整数获取的方法:
let ptr = unsafeAddressOf(obj)
let nullPtr = UnsafePointer<Void>(bitPattern: 0)

/// This gets the address of pointer
let address = nullPtr.distanceTo(ptr) // This is Int

稍作跟进。


以下是适用于Swift 3的答案版本。 - RenniePet

4

我在Swift 3上的解决方案

extension MyClass: CustomStringConvertible {
    var description: String {
        return "<\(type(of: self)): 0x\(String(unsafeBitCast(self, to: Int.self), radix: 16, uppercase: false))>"
    }
}

这段代码创建了一个类似默认描述的描述:<MyClass: 0x610000223340>

3

这是针对Swift 3的。

和@CharlieMonroe一样,我想要将地址作为整数获取。具体来说,我想要获取一个Thread对象的地址,用作诊断日志模块中的线程ID,在没有线程名称可用的情况下。

基于Charlie Monroe的代码,这是我目前想出的东西。但请注意,我非常新手Swift,可能不正确...

  // Convert the memory address of the current Thread object into an Int for use as a thread ID
  let objPtr = Unmanaged.passUnretained(Thread.current).toOpaque()
  let onePtr = UnsafeMutableRawPointer(bitPattern: 1)!  // 1 used instead of 0 to avoid crash
  let rawAddress : Int64 = onePtr.distance(to: objPtr) + 1  // This may include some high-order bits
  let address = rawAddress % (256 * 1024 * 1024 * 1024)  // Remove high-order bits

最后一条语句是必需的,因为如果没有它,我会得到像0x60000007DB3F这样的地址。最后一条语句中的模运算将其转换为0x7DB3F。


1

这绝对不是最快或最安全的方法。但对我来说有效。这将允许任何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

感谢反馈,Jeff。我会更新答案。 - Charlton Provatas
1
没事了!那是我的错误!您的代码在纯Swift类中运行良好。对于我的错误感到抱歉。 - Jeff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接