从C函数更新进度条

3
我正在使用Swift为iOS 8开发一款音频应用程序。该应用程序可以加载MIDI文件,当用户单击“保存”按钮时,它会渲染到文件中。在C函数中,需要手动提取样本。
现在,我想要更新界面上的进度条以反映保存进度。
我在ViewController中添加了一个属性观察器来监测变量,我将这个变量的指针传递给C函数,希望能够在循环过程中更新值。然而,即使C函数在循环内部更新了变量的值,这个更新只会在最后被“触发”。
有没有办法更新进度条?
下面是一些代码。
谢谢!

在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"); 
[…] 
}  
1个回答

1
如果观察无效,为什么不通过NSNotification将更新显式发送到控制器呢?以下是我作为概念验证所做的事情:
  1. Add an Objective-C class file with .h and .m files. No need to define a class in this file, just put your c function in .m, and the declaration in .h.

  2. Configure the bridging header, where you import the .h file. The bridging header is typically called "-Bridging-Header.h".

  3. You can now just call your function in any swift class.

  4. In the .m file with the c function, import "<UIKit/UIkit.h>" (or Foundation).

  5. When needed, post a notification from your c function similar to this:

    NSNotification *notif = [[NSNotification alloc] initWithName:@"Update"
       object:nil userInfo:@{@"progress" : @0.42}];
    [[NSNotificationCenter defaultCenter] postNotification:notif];
    
  6. In the swift file, follow the usual procedure to add self as observer for the notification and call the update function with the values passed in the userInfo dictionary.


我尝试将 &self.progressBarOutlet.progress 传递给 C 函数,但这并不起作用。问题似乎不在于 ViewController 中捕获数据,而是从 C 函数发送数据。此外,如果没有观察者,在主线程中控制器将无法更新,导致界面上出现10秒的延迟。 - popisar
什么意思?C函数已经被ViewController调用了。 - popisar
我不知道你可以在ViewController中编写C函数...你怎么做到的?你能给我一个例子吗?谢谢! - popisar
抱歉,我在想Objective-C。当然不可能了。但是,你不能将控制器传递给函数吗?或者,更好的方法是,让函数发送NSNotifications? - Mundi
请查看我的编辑。我对这个实际上是如何工作很感兴趣。如果您能给我额外的点赞以示支持,我将不胜感激。 - Mundi
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接