从 Objective C 将回调/闭包转换为 Swift
Posted
技术标签:
【中文标题】从 Objective C 将回调/闭包转换为 Swift【英文标题】:Convert callback/closure to Swift from Objective C 【发布时间】:2018-08-30 17:17:34 【问题描述】:所以我正在尝试在 Swift 中实现 Superpowered 库,并且在初始化时遇到了回调。我将如何转换该行:
__unsafe_unretained Superpowered *self = (__bridge Superpowered *)clientdata;
进入斯威夫特?
这是简化的 Objective C 实现:
@implementation Superpowered
SuperpowerediosAudioIO *audioIO;
SuperpoweredBandpassFilterbank *filters;
unsigned int samplerate;
static bool audioProcessing(void *clientdata, float **buffers, unsigned int inputChannels, unsigned int outputChannels, unsigned int numberOfSamples, unsigned int samplerate, uint64_t hostTime)
__unsafe_unretained Superpowered *self = (__bridge Superpowered *)clientdata;
if (samplerate != self->samplerate)
self->samplerate = samplerate;
;
// Update position.
self->lastNumberOfSamples = numberOfSamples;
return false;
- (id)init
self = [super init];
if (!self) return nil;
samplerate = 44100;
audioIO = [[SuperpoweredIOSAudioIO alloc] initWithDelegate:(id<SuperpoweredIOSAudioIODelegate>)self preferredBufferSize:12 preferredMinimumSamplerate:44100 audioSessionCategory:AVAudioSessionCategoryRecord channels:2 audioProcessingCallback:audioProcessing clientdata:(__bridge void *)self];
[audioIO start];
return self;
这是我的 Swift 版本的开始:
func bridge<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
// return unsafeAddressOf(obj) // ***
func bridge<T : AnyObject>(ptr : UnsafeMutableRawPointer) -> T
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
// return unsafeBitCast(ptr, T.self) // ***
open class EchoesEngine: NSObject, CLLocationManagerDelegate, SuperpoweredIOSAudioIODelegate
public var audioIO:SuperpoweredIOSAudioIO
static var lastNumberOfSamples:UInt32!
static var samplerate:UInt32!
override init()
super.init()
audioIO = SuperpoweredIOSAudioIO.init(delegate: self, preferredBufferSize: 12, preferredMinimumSamplerate: 44100, audioSessionCategory: AVAudioSessionCategoryPlayAndRecord, channels: 2, audioProcessingCallback: EchoesEngine.audioProcessingCallback, clientdata: bridge(obj: self))
…
@objc static let audioProcessingCallback : @convention(c) (UnsafeMutableRawPointer?, UnsafeMutablePointer<UnsafeMutablePointer<Float>?>?, UInt32, UInt32, UInt32, UInt32, UInt64) -> Bool =
(clientdata, buffers, inputChannels, outputChannels, numberOfSamples, _samplerate, hostTime) in
/*
let unsafePointer = Unmanaged<EchoesEngine>.fromOpaque(clientdata!).takeUnretainedValue()
let pointer = AutoreleasingUnsafeMutablePointer<EchoesEngine>(unsafePointer)
*/
self = bridge(ptr: clientdata!)
if samplerate != _samplerate
samplerate = _samplerate
lastNumberOfSamples = numberOfSamples
return false
【问题讨论】:
那里不需要__unsafe_unretained
。如果只是让它成为默认值(__strong
),它会在函数结束时保留然后释放,这不会造成任何问题。
感谢@newacct 的评论——但我真的在问如何在 Swift 中实现它! bridge() fns 在那里成功了。
【参考方案1】:
所以我发现,在这种情况下,我试图转换为的 self
实际上是一个新变量,它提供了一个对 self 的 __unsafe_unretained
引用,就像传递给 SuperpoweredIOSAudioIO
的初始化程序一样。
This answer 为我提供了几乎所有我需要的东西。 Swift 3.3 改变了一些东西,这就是我最终的结果:
func bridge<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
// return unsafeAddressOf(obj) // ***
func bridge<T : AnyObject>(ptr : UnsafeMutableRawPointer?) -> T
return Unmanaged<T>.fromOpaque(ptr!).takeUnretainedValue()
// return unsafeBitCast(ptr, T.self) // ***
【讨论】:
以上是关于从 Objective C 将回调/闭包转换为 Swift的主要内容,如果未能解决你的问题,请参考以下文章
从 Swift 调用 Objective C 和 C 传递回调函数