-
-
Save amomchilov/a664fbd2bb0da47a219f826f2a35703e to your computer and use it in GitHub Desktop.
https://stackoverflow.com/questions/61236195/create-a-weak-unsafemutablerawpointer/61236529#61236529
This file contains hidden or 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 Dispatch | |
import Foundation | |
// The Weak struct is the weak wrapper | |
struct Weak<T: AnyObject> { | |
weak var object: T? | |
} | |
// Stand-in for AUGraphAddRenderNotify | |
func call( | |
cCallback: @escaping @convention(c) (UnsafeMutableRawPointer) -> Void, | |
inRefCon: UnsafeMutableRawPointer | |
) { | |
cCallback(inRefCon) // call once immediately | |
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { | |
cCallback(inRefCon) // call once after deallocation of the TestObject | |
} | |
} | |
// A callback that's guarenteed to not capture a TestObject | |
let theCallBack: @convention(c) (UnsafeMutableRawPointer) -> Void = { rawPointer in | |
print("Running callback") | |
let weakWrapperPointer = rawPointer.assumingMemoryBound(to: Weak<TestObject>.self) | |
let weakWrapper = weakWrapperPointer.pointee | |
if let object = weakWrapper.object { | |
print(object.value) | |
} | |
} | |
// TestObject represents the AudioPlayer class | |
class TestObject { | |
let value = "test" | |
init () { | |
print("init") | |
// Create a wrapper for this object | |
let weakWrapper = Weak<TestObject>(object: self) | |
// Create the wrapper pointer | |
let size = MemoryLayout<Weak<TestObject>>.size | |
let weakWrapperPointer = UnsafeMutableRawPointer.allocate(byteCount: size, alignment: 1) | |
weakWrapperPointer.storeBytes(of: weakWrapper, as: Weak<TestObject>.self) | |
// This is the problem. I can't figure out how to get this to work without crashing | |
call(cCallback: theCallBack, inRefCon: weakWrapperPointer) | |
} | |
deinit { | |
print("deinit") | |
} | |
} | |
// Create a test object, which immediately gets deallocated (represents the AudioPlayer) | |
_ = TestObject() | |
RunLoop.main.run(until: Date().addingTimeInterval(2)) | |
print("The end") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@mori-nobuteru if I understand correctly, you’re passing in a strong reference to a WeakVar object (now a class), whereas I was passing in a a raw pointer to the struct.
I like your approach better! It involves one more reference counted object, but it’s semantics are clearer