Andrew Harris
Andrew Harris

Reputation: 416

Why does the iPhone seem to freeze when using a while loop with swift?

I am trying to take a picture every 2 seconds by using a while loop. but when I try this the screen freezes.
This is the function that takes the photo:

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)


            }


        })
    }


}

To take the picture I have a button which will use this function in a while loop when a variable called count is equal to 0, but when the end button is pressed, this variable is equal to 1, so the while loop ends.
This is what the startPictureButton action looks like:

@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)

    }


}

But when I run this and start the timelapse the screen looks frozen.
Does anyone know how to stop the freeze from happening - but also to add each image taken to an array - so that I can turn that into a video?

Upvotes: 1

Views: 895

Answers (2)

FreeNickname
FreeNickname

Reputation: 7814

The problem is that the method that processes clicks on the button (TakeScreanshotClick method) is run on the UI thread. So, if this method never exits, the UI thread gets stuck in it, and the UI freezes.

In order to avoid it, you can run your loop on the background thread (read about NSOperation and NSOperationQueue). Occasionally you might need to dispatch something from the background thread to the UI thread (for instance, commands for UI updates).

UPDATE: Apple has a really great documentation (best of what I've seen so far). Have a look at this: Apple Concurrency Programming Guide.

Upvotes: 5

Tim
Tim

Reputation: 2098

You are calling the sleep command on the main UI thread, thus freezing all other activity.

Also, I can't see where you set count = 1? Wouldn't the while loop continue forever?

Upvotes: 3

Related Questions