For the More Curious: Recording Video

Once you understand how to use UIImagePickerController to take pictures, making the transition to recording video is trivial. Recall that an image picker controller has a sourceType property that determines whether an image comes from the camera, photo library, or saved photos album. Image picker controllers also have a mediaTypes property, which is an array of strings that contains identifiers for what types of media can be selected from the three source types.

There are two types of media a UIImagePickerController can select: still images and video. By default, the mediaTypes array only contains the constant string kUTTypeImage. Thus, if you do not change the mediaTypes property of an image picker controller, the camera will only allow the user to take still photos, and the photo library and saved photos album will only display images.

Adding the ability to record video or choose a video from the disk is as simple as adding the constant string kUTTypeMovie to the mediaTypes array. However, not all devices support video through the UIImagePickerController. Just like the class method isSourceTypeAvailable: allows you to determine if the device has a camera, the availableMediaTypesForSourceType: method checks to see if that camera can capture video. To set up an image picker controller that can record video or take still images, you would write the following code:

 ​ ​ ​ ​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​ ​*​i​p​c​ ​=​ ​[​[​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​
 ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​a​v​a​i​l​a​b​l​e​T​y​p​e​s​ ​=​ ​[​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​a​v​a​i​l​a​b​l​e​M​e​d​i​a​T​y​p​e​s​F​o​r​S​o​u​r​c​e​T​y​p​e​:​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​S​o​u​r​c​e​T​y​p​e​C​a​m​e​r​a​]​;​
 ​ ​ ​ ​[​i​p​c​ ​s​e​t​M​e​d​i​a​T​y​p​e​s​:​a​v​a​i​l​a​b​l​e​T​y​p​e​s​]​;​
 ​ ​ ​ ​[​i​p​c​ ​s​e​t​S​o​u​r​c​e​T​y​p​e​:​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​S​o​u​r​c​e​T​y​p​e​C​a​m​e​r​a​]​;​
 ​ ​ ​ ​[​i​p​c​ ​s​e​t​D​e​l​e​g​a​t​e​:​s​e​l​f​]​;​

Now when this image picker controller interface is presented to the user, there will be a switch that allows them to choose between the still image camera or the video recorder. If the user chooses to record a video, you need to handle that in the UIImagePickerController delegate method imagePickerController:​didFinishPickingMediaWithInfo:.

When dealing with still images, the info dictionary that is passed as an argument contains the full image as a UIImage object. However, there is no UIVideo class. (Loading an entire video into memory at once would be tough to do with device memory constraints.) Therefore, recorded video is written to disk in a temporary directory. When the user finalizes the video recording, imagePickerController:​didFinishPickingMediaWithInfo: is sent to the image picker controller’s delegate, and the path of the video on the disk is in the info dictionary. You can get the path like so:

-​ ​(​v​o​i​d​)​i​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​:​(​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​ ​*​)​p​i​c​k​e​r​
d​i​d​F​i​n​i​s​h​P​i​c​k​i​n​g​M​e​d​i​a​W​i​t​h​I​n​f​o​:​(​N​S​D​i​c​t​i​o​n​a​r​y​ ​*​)​i​n​f​o​
{​
 ​ ​ ​ ​N​S​U​R​L​ ​*​m​e​d​i​a​U​R​L​ ​=​ ​[​i​n​f​o​ ​o​b​j​e​c​t​F​o​r​K​e​y​:​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​M​e​d​i​a​U​R​L​]​;​
}​

We will talk about the filesystem in Chapter 15, but what you should know now is that the temporary directory is not a safe place to store the video. It needs to be moved to another location.

-​ ​(​v​o​i​d​)​i​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​:​(​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​ ​*​)​p​i​c​k​e​r​
d​i​d​F​i​n​i​s​h​P​i​c​k​i​n​g​M​e​d​i​a​W​i​t​h​I​n​f​o​:​(​N​S​D​i​c​t​i​o​n​a​r​y​ ​*​)​i​n​f​o​
{​
 ​ ​ ​ ​N​S​U​R​L​ ​*​m​e​d​i​a​U​R​L​ ​=​ ​[​i​n​f​o​ ​o​b​j​e​c​t​F​o​r​K​e​y​:​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​M​e​d​i​a​U​R​L​]​;​
 ​ ​ ​ ​i​f​ ​(​m​e​d​i​a​U​R​L​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​M​a​k​e​ ​s​u​r​e​ ​t​h​i​s​ ​d​e​v​i​c​e​ ​s​u​p​p​o​r​t​s​ ​v​i​d​e​o​s​ ​i​n​ ​i​t​s​ ​p​h​o​t​o​ ​a​l​b​u​m​
 ​ ​ ​ ​ ​ ​ ​ ​i​f​ ​(​U​I​V​i​d​e​o​A​t​P​a​t​h​I​s​C​o​m​p​a​t​i​b​l​e​W​i​t​h​S​a​v​e​d​P​h​o​t​o​s​A​l​b​u​m​(​[​m​e​d​i​a​U​R​L​ ​p​a​t​h​]​)​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​S​a​v​e​ ​t​h​e​ ​v​i​d​e​o​ ​t​o​ ​t​h​e​ ​p​h​o​t​o​s​ ​a​l​b​u​m​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​U​I​S​a​v​e​V​i​d​e​o​A​t​P​a​t​h​T​o​S​a​v​e​d​P​h​o​t​o​s​A​l​b​u​m​(​[​m​e​d​i​a​U​R​L​ ​p​a​t​h​]​,​ ​n​i​l​,​ ​n​i​l​,​ ​n​i​l​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​R​e​m​o​v​e​ ​t​h​e​ ​v​i​d​e​o​ ​f​r​o​m​ ​t​h​e​ ​t​e​m​p​o​r​a​r​y​ ​d​i​r​e​c​t​o​r​y​ ​i​t​ ​w​a​s​ ​s​a​v​e​d​ ​a​t​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​[​N​S​F​i​l​e​M​a​n​a​g​e​r​ ​d​e​f​a​u​l​t​M​a​n​a​g​e​r​]​ ​r​e​m​o​v​e​I​t​e​m​A​t​P​a​t​h​:​[​m​e​d​i​a​U​R​L​ ​p​a​t​h​]​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​r​r​o​r​:​n​i​l​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​}​
 ​ ​ ​ ​}​
}​

That is really all there is to it. There is just one situation that requires some additional information: suppose you want to restrict the user to choosing only videos. Restricting the user to images is simple (leave mediaTypes as the default). Allowing the user to choose between images and videos is just as simple (pass the return value from availableMediaTypesForSourceType:). However, to allow video only, you have to jump through a few hoops. First, you must make sure the device supports video and then set the mediaTypes property to an array containing the identifier for video only.

 ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​a​v​a​i​l​a​b​l​e​T​y​p​e​s​ ​=​ ​[​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​a​v​a​i​l​a​b​l​e​M​e​d​i​a​T​y​p​e​s​F​o​r​S​o​u​r​c​e​T​y​p​e​:​U​I​I​m​a​g​e​P​i​c​k​e​r​C​o​n​t​r​o​l​l​e​r​S​o​u​r​c​e​T​y​p​e​C​a​m​e​r​a​]​;​

 ​ ​ ​ ​i​f​ ​(​[​a​v​a​i​l​a​b​l​e​T​y​p​e​s​ ​c​o​n​t​a​i​n​s​O​b​j​e​c​t​:​(​N​S​S​t​r​i​n​g​ ​*​)​k​U​T​T​y​p​e​M​o​v​i​e​]​)​
 ​ ​ ​ ​ ​ ​ ​ ​[​i​p​c​ ​s​e​t​M​e​d​i​a​T​y​p​e​s​:​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​:​(​N​S​S​t​r​i​n​g​ ​*​)​k​U​T​T​y​p​e​M​o​v​i​e​]​]​;​

Wondering why kUTTypeMovie is cast to an NSString? This constant is declared as:

 ​ ​ ​ ​c​o​n​s​t​ ​C​F​S​t​r​i​n​g​R​e​f​ ​k​U​T​T​y​p​e​V​i​d​e​o​;​

If you build this code, it will fail, and the compiler will complain that it’s never heard of kUTTypeMovie. Oddly enough, both kUTTypeMovie and kUTTypeImage are declared and defined in another framework – MobileCoreServices. You have to explicitly add this framework and import its header file into your project to use these two constants.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.109.8