Created
January 25, 2024 17:10
-
-
Save pookjw/b1edac0c1cfd73b8f9a84da4378d0706 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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