Skip to content

Instantly share code, notes, and snippets.

@pookjw
Created January 25, 2024 17:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pookjw/b1edac0c1cfd73b8f9a84da4378d0706 to your computer and use it in GitHub Desktop.
Save pookjw/b1edac0c1cfd73b8f9a84da4378d0706 to your computer and use it in GitHub Desktop.
import Foundation
import CoreFoundation
// https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFCollections/Articles/creating.html#//apple_ref/doc/uid/20001132-101215-CHDEBBDB
class MyObject: NSObject {
var string: NSString
init(string: NSString) {
self.string = string
super.init()
}
deinit {
print("deinit!!!")
}
override func copy() -> Any {
MyObject(string: string.copy() as! NSString)
}
}
let retainCallBack: CFDictionaryRetainCallBack = { allocator, ptr in
UnsafeRawPointer(Unmanaged<AnyObject>.passRetained(unsafeBitCast(ptr, to: AnyObject.self)).toOpaque())
}
let releaseCallBack: CFDictionaryReleaseCallBack = { allocator, ptr in
Unmanaged<AnyObject>.passUnretained(unsafeBitCast(ptr, to: AnyObject.self)).release()
}
let copyDescriptionCallBack: CFDictionaryCopyDescriptionCallBack = { ptr in
let value: AnyObject = unsafeBitCast(ptr, to: AnyObject.self)
let result: AnyObject = (value.copy?() as? AnyObject) ?? value
let format: CFString = CFStringCreateWithCString(kCFAllocatorDefault, "[%@]", CFStringBuiltInEncodings.UTF8.rawValue)
let args: [CVarArg] = [UInt(bitPattern: Unmanaged<AnyObject>.passRetained(result).toOpaque())]
let description: CFString = withVaList(args) { p in
CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, nil, format, p)
}
return Unmanaged<CFString>.passRetained(description)
}
let equalCallBack: CFDictionaryEqualCallBack = { lhsPtr, rhsPtr in
let lhsObject: AnyObject = unsafeBitCast(lhsPtr, to: AnyObject.self)
let rhsObject: AnyObject = unsafeBitCast(rhsPtr, to: AnyObject.self)
return .init(lhsObject.isEqual(rhsObject))
}
let hashCallBack: CFDictionaryHashCallBack = { ptr in
return .init(unsafeBitCast(ptr, to: AnyObject.self).hash ?? .zero)
}
let valueCallBacks: CFDictionaryValueCallBacks = .init(
version: .zero,
retain: retainCallBack,
release: releaseCallBack,
copyDescription: copyDescriptionCallBack,
equal: equalCallBack
)
autoreleasepool {
let dictionary: CFMutableDictionary = withUnsafePointer(to: valueCallBacks) { p in
CFDictionaryCreateMutable(
kCFAllocatorDefault,
1,
nil,
p
)
}
let object: MyObject = .init(string: "Test")
CFDictionarySetValue(dictionary, .init(bitPattern: 3), Unmanaged<MyObject>.passUnretained(object).toOpaque())
CFShow(dictionary)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment