从 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, ¤tTime), "MusicPlayerGetTime");
*outProgressBarValue = currentTime / sequenceLength;
printf("outProgressBarValue:\t %f\n", *outProgressBarValue);
} while (currentTime < sequenceLength);
CheckError(MusicPlayerStop(musicPlayer), "MusicPlayerStop");
[…]
}
如果观察不起作用,为什么不将更新显式发送到控制器?例如,通过 NSNotification。
这是我做的概念验证:
添加一个包含 .h 和 .m 文件的 Objective-C class 文件。无需在此文件中定义 class,只需将您的 c 函数放在 .m 中,将声明放在 .h 中即可。
配置桥接 header,在其中导入 .h 文件。桥接 header 通常称为“-Bridging-Header.h”。
您现在可以在任何 swift class 中调用您的函数。
在带有c函数的.m文件中,导入“<UIKit/UIkit.h>
”(或Foundation)。
需要时,post 来自您的 c 函数的通知类似于:
NSNotification *notif = [[NSNotification alloc] initWithName:@"Update"
object:nil userInfo:@{@"progress" : @0.42}];
[[NSNotificationCenter defaultCenter] postNotification:notif];
在swift文件中,按照通常的步骤将self
添加为通知的观察者,并使用[=13=中传递的值调用更新函数] 词典。
我正在为 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, ¤tTime), "MusicPlayerGetTime");
*outProgressBarValue = currentTime / sequenceLength;
printf("outProgressBarValue:\t %f\n", *outProgressBarValue);
} while (currentTime < sequenceLength);
CheckError(MusicPlayerStop(musicPlayer), "MusicPlayerStop");
[…]
}
如果观察不起作用,为什么不将更新显式发送到控制器?例如,通过 NSNotification。
这是我做的概念验证:
添加一个包含 .h 和 .m 文件的 Objective-C class 文件。无需在此文件中定义 class,只需将您的 c 函数放在 .m 中,将声明放在 .h 中即可。
配置桥接 header,在其中导入 .h 文件。桥接 header 通常称为“-Bridging-Header.h”。
您现在可以在任何 swift class 中调用您的函数。
在带有c函数的.m文件中,导入“
<UIKit/UIkit.h>
”(或Foundation)。需要时,post 来自您的 c 函数的通知类似于:
NSNotification *notif = [[NSNotification alloc] initWithName:@"Update" object:nil userInfo:@{@"progress" : @0.42}]; [[NSNotificationCenter defaultCenter] postNotification:notif];
在swift文件中,按照通常的步骤将
self
添加为通知的观察者,并使用[=13=中传递的值调用更新函数] 词典。