The worst problems that happen in software development are the ones that happen behind the curtains. Use the memory profiler in Xcode to examine the performance of your camera in different situations, and then introduce a deliberate memory leak into the camera so you can see what a memory leak looks like, how to debug it, and how to make sure you write clean code—protecting your framework against situations like that.
- [Instructor] Before we get ready to start shipping our framework, and make it releasable, it's very, very important to make sure that you're always checking for memory leaks in any application or framework that you work with. Let's go over how to enable the memory debugger in Xcode 9. Go up to your schemes, and click on Edit Scheme for your SampleApplication. In the Run tab, you'll initially end up on the Info screen here. Go to the right and click on Diagnostics. Go down to where it says Logging, click on Malloc Stack, and under the options you have here, click on Live Allocations Only.
The reason we're choosing Live Allocations Only is because automatic resource counting will take care of most of our work for us. We'll need to focus on what's live on the stack that we're working with. Click on Close, and go ahead and run your application. As we've been working on this, we've actually built in a retain cycle into our application, that we know how to debug now that we have the memory debugger. Let's go ahead and show that so we can access where the leak is, and put in a fix for it. On your sample application, tap the Start button, so that the camera pulls up.
Hit the Cancel button, and hit the Start button one more time. Go back to Xcode, and click this button for the memory debugger. When you hover your mouse over, it should say Debug Memory Graph. Your application will pause, and as you scroll through the left, you'll be able to look at all of the different memory graphs that you have for objects here. You'll notice here that we have some leaks that are already apparent to us. Another way to see this is to go up to your Errors pane at the top of your issue navigator, and click on Runtime, and you'll see that there are two leaked types here. Let's look at this first one.
If we click here, open the dropdown menu and click this, you'll notice that we have a leak between our Camera and our CameraViewController. If you click this number three, you'll notice here, we've gone to the camera, but then we reference back to both the delegate and the controller. Let's take a look at what exactly we did there. If you go back to your Camera.swift file, and scroll to the top, you'll notice that we have a reference to our Controller. Yes, we did mark it as optional, but there's really no need to have a reference back to our Controller if we already have a delegate communicating back to it.
This is a bug that we can fix. First things first, go ahead and delete this var. We're going to fix the logic up to make sure that we don't need this on our Camera object. You'll see a couple of other errors pop up, and you'll notice that our constructor includes that controller. Not only do we need to get rid of this statement here, but we need to get rid of the parameters inside of our constructor. Delete everything inside that set of parentheses. Xcode will pop up one more time, saying that you need to include an override keyword if you're not specifying any parameters in your constructor. Go ahead and let it automatically fix this for you.
Try to build your sample application and it will alert to one more error still. In the function getPreviewLayer, you can look here what we did. We made sure that we had a controller on this object, and then we used the controller view balance to decide what the frame of the preview layer would be. In all honesty, we need to be doing this on the UI view controller class, and not inside the camera object. This means that we can get rid of this logic to make sure that we have a controller. And we can get rid of setting the previewLayer.frame in the camera object. However, just because we've deleted this and gotten rid of the reference inside of our camera object, we do still need to make sure that we're setting the frame on our previewLayer.
Go back up to CameraViewController, and try building your sample application to make our bugs apparent to us. As you scroll down, you'll notice that the constructor for camera no longer includes a parameter, so you can get rid of everything inside of your parentheses. Finally, we need to go to the place where we call getPreviewLayer. Go ahead and search for wherever that function is called, and it should take you to the createUI function. Because we're not specifying a frame for the previewLayer inside of our camera function, we need to do that here. This makes more sense because we have easy access to our view controller frame here, so we can simply type previewLayer.frame = self.view.bounds.
This means that we've now eliminated a double reference back to our view controller from our camera via both the delegate and the reference that we're stashing to it. Go ahead and build your sample application one more time. Just like before, hit Start, then hit Cancel, and hit Start one more time. Go back into Xcode, and hit the Memory Debug Graph again. Go up to your Runtime issues. It's important to point out that there still are a couple of other leaks that you would want to take a look at here, and those are relatively easy to fix, but if you look at the instance of the Camera that we've leaked, we've fixed the retain cycle that we've had, and we now only have the delegate pointing back to our view controller from our camera.
This is how you can make use of the memory debugger to take care of hidden issues in your framework.
Along the way, he explains the differences and nuances between writing code for an application and for a reusable framework, as well as some of the fundamentals of AVFoundation, one of the core camera frameworks in iOS. David also shows how to refactor your code, understand Swift access control, develop an interface, and handle memory leaks, so your framework is ready to share with other developers.
- Creating your first build
- Making the camera work
- Creating a framework delegate
- Adding media
- Capturing images
- Correcting orientation
- Versioning and tagging releases in Git