从 C 函数更新进度条

Update a progress bar from a C function

我正在为 Swift 中的 iOS 8 开发一个音频应用程序。 加载 MIDI 文件,当用户按下 "Save" 按钮时,它会呈现为 C 函数中的文件,该函数手动提取样本。
现在,我想为这个保存操作更新界面中的进度条。
我向 ViewController 中的 var 添加了一个 属性 观察器,并将指向此 var 的指针传递给 C 函数,希望它会在循环期间更新它……好吧,没有。 即使 C 函数在循环内更新 var 的值,这个更新也只是 "fired" 一次,在最后。 有没有办法更新进度条?
这是一些代码。
谢谢!

在ViewController中:

var outProgressBarValue:Float = 0.0 {
    willSet {
        dispatch_async(dispatch_get_main_queue(), {
            println("New value received! -> \(newValue)")
            self.progressBarOutlet.setProgress(newValue, animated: true)
        })
    }
}

@IBAction func saveButton(sender: AnyObject) {
    [...]
    let backgroundQueue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)
    dispatch_async(backgroundQueue, {
        WriteOutputFile(url, self.musicSequence!, Sound.sharedInstance.musicPlayer, self.processingGraph,  &self.outProgressBarValue)

    dispatch_async(dispatch_get_main_queue(), {
            restoreOnlineRendering(processingGraph: self.processingGraph, mainMixerNode: self.mainMixerNode, ioNode: &(self.ioNode))
            self.saveButtonOutlet.setTitle("Done", forState: UIControlState.Normal)
    [...]
}

在链接的 C 文件中:

void WriteOutputFile(CFURLRef url, MusicSequence musicSequence, MusicPlayer musicPlayer, AUGraph processingGraph, float *outProgressBarValue) {  
[…] 
    CheckError(MusicPlayerStart(musicPlayer), "MusicPlayerStart");
    do {
        CheckError(AudioUnitRender (outputUnit, &actionFlags, &tStamp, 0, numFrames, bufferList), "AudioUnitRender");
        tStamp.mSampleTime += (Float64)numFrames;
        CheckError(ExtAudioFileWrite(outfile, numFrames, bufferList), "ExtAudioFileWrite");
        CheckError(MusicPlayerGetTime (musicPlayer, &currentTime), "MusicPlayerGetTime");
        *outProgressBarValue = currentTime / sequenceLength;
        printf("outProgressBarValue:\t %f\n", *outProgressBarValue);
    } while (currentTime < sequenceLength);

    CheckError(MusicPlayerStop(musicPlayer), "MusicPlayerStop"); 
[…] 
}  

如果观察不起作用,为什么不将更新显式发送到控制器?例如,通过 NSNotification。

这是我做的概念验证:

  1. 添加一个包含 .h 和 .m 文件的 Objective-C class 文件。无需在此文件中定义 class,只需将您的 c 函数放在 .m 中,将声明放在 .h 中即可。

  2. 配置桥接 header,在其中导入 .h 文件。桥接 header 通常称为“-Bridging-Header.h”。

  3. 您现在可以在任何 swift class 中调用您的函数。

  4. 在带有c函数的.m文件中,导入“<UIKit/UIkit.h>”(或Foundation)。

  5. 需要时,post 来自您的 c 函数的通知类似于:

    NSNotification *notif = [[NSNotification alloc] initWithName:@"Update"
       object:nil userInfo:@{@"progress" : @0.42}];
    [[NSNotificationCenter defaultCenter] postNotification:notif];
    
  6. 在swift文件中,按照通常的步骤将self添加为通知的观察者,并使用[=13=中传递的值调用更新函数] 词典。