为什么在 swift 中使用 while 循环时 iPhone 似乎冻结了?
Why does the iPhone seem to freeze when using a while loop with swift?
我正在尝试使用 while 循环每 2 秒拍一张照片。但是当我尝试这个时,屏幕冻结了。
这是拍照的功能:
func didPressTakePhoto(){
if let videoConnection = stillImageOutput?.connectionWithMediaType(AVMediaTypeVideo){
videoConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: {
(sampleBuffer, error) in
if sampleBuffer != nil {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let dataProvider = CGDataProviderCreateWithCFData(imageData)
let cgImageRef = CGImageCreateWithJPEGDataProvider(dataProvider, nil, true, .RenderingIntentDefault)
let image = UIImage(CGImage: cgImageRef!, scale: 1.0, orientation: UIImageOrientation.Right)
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
//Adds every image taken to an array each time the while loop loops which will then be used to create a timelapse.
self.images.append(image)
}
})
}
}
为了拍照,我有一个按钮,当一个名为 count 的变量等于 0 时,它会在 while 循环中使用这个函数,但是当按下结束按钮时,这个变量等于 1,所以 while循环结束。
这是 startPictureButton 操作的样子:
@IBAction func TakeScreanshotClick(sender: AnyObject) {
TipsView.hidden = true
XBtnTips.hidden = true
self.takePictureBtn.hidden = true
self.stopBtn.hidden = false
controls.hidden = true
ExitBtn.hidden = true
PressedLbl.text = "Started"
print("started")
while count == 0{
didPressTakePhoto()
print(images)
pressed = pressed + 1
PressedLbl.text = "\(pressed)"
print(pressed)
sleep(2)
}
}
但是当我 运行 这并开始延时时,屏幕看起来冻结了。
有谁知道如何阻止冻结的发生 - 以及如何将拍摄的每张图像添加到一个数组 - 以便我可以将其转换为视频?
您正在主 UI 线程上调用睡眠命令,因此冻结所有其他 activity。
另外,我没看到你在哪里设置了count = 1? while 循环不会永远持续下去吗?
问题是处理按钮点击的方法(TakeScreanshotClick
方法)是 UI 线程上的 运行。因此,如果此方法永远不会退出,UI 线程就会卡在其中,并且 UI 会冻结。
为了避免它,您可以 运行 在后台线程上循环(阅读 NSOperation
和 NSOperationQueue
)。有时您可能需要将某些内容从后台线程分派到 UI 线程(例如,UI 更新的命令)。
更新:Apple 拥有非常棒的文档(迄今为止我所见过的最好的文档)。看看这个:Apple Concurrency Programming Guide.
我正在尝试使用 while 循环每 2 秒拍一张照片。但是当我尝试这个时,屏幕冻结了。
这是拍照的功能:
func didPressTakePhoto(){
if let videoConnection = stillImageOutput?.connectionWithMediaType(AVMediaTypeVideo){
videoConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: {
(sampleBuffer, error) in
if sampleBuffer != nil {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let dataProvider = CGDataProviderCreateWithCFData(imageData)
let cgImageRef = CGImageCreateWithJPEGDataProvider(dataProvider, nil, true, .RenderingIntentDefault)
let image = UIImage(CGImage: cgImageRef!, scale: 1.0, orientation: UIImageOrientation.Right)
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
//Adds every image taken to an array each time the while loop loops which will then be used to create a timelapse.
self.images.append(image)
}
})
}
}
为了拍照,我有一个按钮,当一个名为 count 的变量等于 0 时,它会在 while 循环中使用这个函数,但是当按下结束按钮时,这个变量等于 1,所以 while循环结束。
这是 startPictureButton 操作的样子:
@IBAction func TakeScreanshotClick(sender: AnyObject) {
TipsView.hidden = true
XBtnTips.hidden = true
self.takePictureBtn.hidden = true
self.stopBtn.hidden = false
controls.hidden = true
ExitBtn.hidden = true
PressedLbl.text = "Started"
print("started")
while count == 0{
didPressTakePhoto()
print(images)
pressed = pressed + 1
PressedLbl.text = "\(pressed)"
print(pressed)
sleep(2)
}
}
但是当我 运行 这并开始延时时,屏幕看起来冻结了。
有谁知道如何阻止冻结的发生 - 以及如何将拍摄的每张图像添加到一个数组 - 以便我可以将其转换为视频?
您正在主 UI 线程上调用睡眠命令,因此冻结所有其他 activity。
另外,我没看到你在哪里设置了count = 1? while 循环不会永远持续下去吗?
问题是处理按钮点击的方法(TakeScreanshotClick
方法)是 UI 线程上的 运行。因此,如果此方法永远不会退出,UI 线程就会卡在其中,并且 UI 会冻结。
为了避免它,您可以 运行 在后台线程上循环(阅读 NSOperation
和 NSOperationQueue
)。有时您可能需要将某些内容从后台线程分派到 UI 线程(例如,UI 更新的命令)。
更新:Apple 拥有非常棒的文档(迄今为止我所见过的最好的文档)。看看这个:Apple Concurrency Programming Guide.