1. Trang chủ
  2. » Công Nghệ Thông Tin

iOS 5 Programming Cookbook phần 8 ppt

89 368 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 89
Dung lượng 3,12 MB

Nội dung

[self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { __block BOOL foundTheVideo = NO; [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { /* Get the asset type */ NSString *assetType = [result valueForProperty:ALAssetPropertyType]; if ([assetType isEqualToString:ALAssetTypeVideo]){ NSLog(@"This is a video asset"); foundTheVideo = YES; *stop = YES; /* Get the asset's representation object */ ALAssetRepresentation *assetRepresentation = [result defaultRepresentation]; const NSUInteger BufferSize = 1024; uint8_t buffer[BufferSize]; NSUInteger bytesRead = 0; long long currentOffset = 0; NSError *readingError = nil; /* Find the documents folder (an array) */ NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); /* Retrieve the one documents folder that we need */ NSString *documentsFolder = [documents objectAtIndex:0]; /* Construct the path where the video has to be saved */ NSString *videoPath = [documentsFolder stringByAppendingPathComponent:@"Temp.MOV"]; NSFileManager *fileManager = [[NSFileManager alloc] init]; /* Create the file if it doesn't exist already */ if ([fileManager fileExistsAtPath:videoPath] == NO){ [fileManager createFileAtPath:videoPath contents:nil attributes:nil]; } /* We will use this file handle to write the contents of the media assets to the disk */ NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:videoPath]; 11.7 Retrieving Assets from the Assets Library | 607 do{ /* Read as many bytes as we can put in the buffer */ bytesRead = [assetRepresentation getBytes:(uint8_t *)&buffer fromOffset:currentOffset length:BufferSize error:&readingError]; /* If we couldn't read anything, we will exit this loop */ if (bytesRead == 0){ break; } /* Keep the offset up to date */ currentOffset += bytesRead; /* Put the buffer into an NSData */ NSData *readData = [[NSData alloc] initWithBytes:(const void *)buffer length:bytesRead]; /* And write the data to file */ [fileHandle writeData:readData]; } while (bytesRead > 0); NSLog(@"Finished reading and storing the \ video in the documents folder"); } }]; if (foundTheVideo){ *stop = YES; } } failureBlock:^(NSError *error) { NSLog(@"Failed to enumerate the asset groups."); }]; }); } - (void)viewDidUnload{ [super viewDidUnload]; self.assetsLibrary = nil; } This is what’s happening in our sample code: 608 | Chapter 11: Camera and the Photo Library • We get the default representation of the first video asset that we find in the Assets Library. • We create a file called Temp.MOV in our application’s Documents folder to save the contents of the video asset. • We create a loop that runs so long as there is still data in the asset representation waiting to be read. The getBytes:fromOffset:length:error: instance method of our asset representation object reads as many bytes as we can fit into our buffer for as many times as necessary until we get to the end of the representation data. • After reading the data into our buffer, we encapsulate the data into an object of type NSData using the initWithBytes:length: initialization method of NSData. We then write this data to the file we created previously using the writeData: instance method of NSFileHandle. 11.8 Editing Videos on an iOS Device Problem You want the user of your application to be able to edit videos straight from your application. Solution Use the UIVideoEditorController class. In this example, we will use this class in con- junction with an image picker controller. First we will ask the user to pick a video from her photo library. After she does, we will display an instance of the video editor con- troller and allow the user to edit the video she picked. Discussion The UIVideoEditorController in the iOS SDK allows programmers to display a video editor interface to the users of their applications. All you have to do is to provide the URL of the video that needs to be edited and then present the video editor controller as a modal view. You should not overlay the view of this controller with any other views and you should not modify this view. Calling the presentModalViewController:animated: method immediate- ly after calling the dismissModalViewControllerAnimated: method of a view controller will terminate your application with a runtime error. You must wait for the first view controller to be dismissed and then present the second view controller. You can take advantage of the viewDidAppear: instance method of your view controllers to detect when your view is displayed. You know at this point that any modal view controllers must have disappeared. 11.8 Editing Videos on an iOS Device | 609 So let's go ahead and declare our view controller and any necessary properties: #import <UIKit/UIKit.h> #import <AssetsLibrary/AssetsLibrary.h> #import <MobileCoreServices/MobileCoreServices.h> @interface Editing_Videos_on_an_iOS_DeviceViewController : UIViewController <UINavigationControllerDelegate, UIVideoEditorControllerDelegate, UIImagePickerControllerDelegate> @property (nonatomic, strong) NSURL *videoURLToEdit; @end The UIVideoEditorController is not designed to work in landscape mode. Even if the view controller that displays an instance of the video editor supports all orientations, the video editor will be shown in por- trait mode only. Now let's go ahead and synthesize our video URL property: #import "Editing_Videos_on_an_iOS_DeviceViewController.h" @implementation Editing_Videos_on_an_iOS_DeviceViewController @synthesize videoURLToEdit; The next thing to do is to handle different video editor delegate messages in our view controller: - (void)videoEditorController:(UIVideoEditorController *)editor didSaveEditedVideoToPath:(NSString *)editedVideoPath{ NSLog(@"The video editor finished saving video"); NSLog(@"The edited video path is at = %@", editedVideoPath); [editor dismissModalViewControllerAnimated:YES]; } - (void)videoEditorController:(UIVideoEditorController *)editor didFailWithError:(NSError *)error{ NSLog(@"Video editor error occurred = %@", error); [editor dismissModalViewControllerAnimated:YES]; } - (void)videoEditorControllerDidCancel:(UIVideoEditorController *)editor{ NSLog(@"The video editor was cancelled"); [editor dismissModalViewControllerAnimated:YES]; } 610 | Chapter 11: Camera and the Photo Library When our view loads, we need to display a video picker to the user. She will then be able to pick a video from her library and we will then proceed to allow her to edit that video: - (BOOL) cameraSupportsMedia:(NSString *)paramMediaType sourceType:(UIImagePickerControllerSourceType)paramSourceType{ __block BOOL result = NO; if ([paramMediaType length] == 0){ NSLog(@"Media type is empty."); return NO; } NSArray *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:paramSourceType]; [availableMediaTypes enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) { NSString *mediaType = (NSString *)obj; if ([mediaType isEqualToString:paramMediaType]){ result = YES; *stop= YES; } }]; return result; } - (BOOL) canUserPickVideosFromPhotoLibrary{ return [self cameraSupportsMedia:(__bridge NSString *)kUTTypeMovie sourceType:UIImagePickerControllerSourceTypePhotoLibrary]; } - (BOOL) isPhotoLibraryAvailable{ return [UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypePhotoLibrary]; } - (void)viewDidLoad { [super viewDidLoad]; if ([self isPhotoLibraryAvailable] && [self canUserPickVideosFromPhotoLibrary]){ UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; 11.8 Editing Videos on an iOS Device | 611 /* Set the source type to photo library */ imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; /* And we want our user to be able to pick movies from the library */ NSArray *mediaTypes = [[NSArray alloc] initWithObjects: (__bridge NSString *)kUTTypeMovie, nil]; imagePicker.mediaTypes = mediaTypes; /* Set the delegate to the current view controller */ imagePicker.delegate = self; /* Present our image picker */ [self.navigationController presentModalViewController:imagePicker animated:YES]; } } We now need to know when the user is done picking a video so let's handle various delegate methods of our image picker control: - (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ NSLog(@"Picker returned successfully."); NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType]; if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]){ self.videoURLToEdit = [info objectForKey:UIImagePickerControllerMediaURL]; } [picker dismissModalViewControllerAnimated:YES]; } - (void) imagePickerControllerDidCancel:(UIImagePickerController *)picker{ NSLog(@"Picker was cancelled"); self.videoURLToEdit = nil; [picker dismissModalViewControllerAnimated:YES]; } And when our view appears to the user after she has selected a video from the assets library on her device, we can proceed to display the video editor: - (void) viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; if (self.videoURLToEdit != nil){ 612 | Chapter 11: Camera and the Photo Library NSString *videoPath = [self.videoURLToEdit path]; /* First let's make sure the video editor is able to edit the video at the path in our documents folder */ if ([UIVideoEditorController canEditVideoAtPath:videoPath]){ /* Instantiate the video editor */ UIVideoEditorController *videoEditor = [[UIVideoEditorController alloc] init]; /* We become the delegate of the video editor */ videoEditor.delegate = self; /* Make sure to set the path of the video */ videoEditor.videoPath = videoPath; /* And present the video editor */ [self.navigationController presentModalViewController:videoEditor animated:YES]; self.videoURLToEdit = nil; } else { NSLog(@"Cannot edit the video at this path"); } } } In our example, the user is allowed to pick any video from the photo library. Once she does, we will display the video editor controller by providing the path of the video that the video picker passes to us in a delegate method. The video editor controller’s delegate gets important messages about the state of the video editor. This delegate object must conform to the UIVideoEditorControllerDele gate and UINavigationControllerDelegate protocols. In our example, we chose our view controller to become the delegate of our video editor. Once the editing is done, the delegate object receives the videoEditorController:didSaveEditedVideoToPath: delegate method from the video editor controller. The path of the edited video will be passed through the didSaveEditedVideoToPath parameter. Before attempting to display the interface of the video editor to your users, you must call the canEditVideoAtPath: class method of UIVideoEditorController to make sure the path you are trying to edit is editable by the controller. If the return value of this class method is YES, proceed to configuring and displaying the video editor’s interface. If not, take a separate path, perhaps displaying an alert to your user. See Also Recipe 11.6; Recipe 11.7 11.8 Editing Videos on an iOS Device | 613 CHAPTER 12 Multitasking 12.0 Introduction Multitasking enables background execution, which means the application can keep working as usual—running tasks, spawning new threads, listening for notifications, and reacting to events—but simply does not display anything on the screen or have any way to interact with the user. When the user presses the Home button on the device, which in previous versions of the iPhone and iPad would terminate the application, the application is now sent into the background. An application running on an iOS version that supports multitasking is, by default, opted into background execution. If you link your application against iOS SDK 4.0 and later, you can opt out of background execution, as you will see in Recipe 12.10. If you do, your application will be terminated when the user presses the Home button, as before. When our application moves to the background (such as when the user presses the Home button) and then back to the foreground (when the user selects the application again), various messages are sent by the system and are expected to be received by an object we designate as our application delegate. For instance, when our application is sent to the background, our application delegate will receive the applicationDidEnter Background: method, and as the application comes back to the foreground by the user, the application delegate will receive the applicationWillEnterForeground: delegate message. In addition to these delegate messages, iOS also sends notifications to the running application when it transitions the application to the background and from the back- ground to the foreground. The notification that gets sent when the application is moved to the background is UIApplicationDidEnterBackgroundNotification, and the notification that gets sent when an application transitions from the background to the foreground is UIApplicationWillEnterForegroundNotification. You can use the default notification center to register for these notifications. 615 12.1 Detecting the Availability of Multitasking Problem You want to find out whether the iOS device running your application supports mul- titasking. Solution Call the isMultitaskingSupported instance method of UIDevice, like so: - (BOOL) isMultitaskingSupported{ BOOL result = NO; if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]){ result = [[UIDevice currentDevice] isMultitaskingSupported]; } return result; } - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ if ([self isMultitaskingSupported]){ NSLog(@"Multitasking is supported."); } else { NSLog(@"Multitasking is not supported."); } self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; } Discussion Your application, depending on the iOS devices it targets, can be run and executed on a variety of devices on different operating systems. For instance, if you compile your application with iOS SDK 5.0 and your deployment target OS is 4.0, your application can be run on the iPhone 3G, iPhone 3GS, iPhone 4, and iPod Touch (second and third generations), provided that the iOS on these devices has been updated to iOS 4.0 or iOS 5. Furthermore, a device could have iOS 5.0 or later installed on it, but the under- lying hardware might not be strong enough for multitasking to be supported. Because of this, your application must be aware of whether multitasking is enabled on that specific hardware and on that specific iOS before attempting to act like a multitasking application. 616 | Chapter 12: Multitasking [...]... dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(dispatchQueue, ^(void) { NSError *audioSessionError = nil; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; if ([audioSession setCategory:AVAudioSessionCategoryPlayback error:&audioSessionError]){ NSLog(@"Successfully set the audio session."); } else { NSLog(@"Could not set the audio session"); } NSBundle... Background | 6 35 12.6 Saving and Loading the State of Multitasking iOS Apps Problem You want the state of your iOS app to be saved when it is sent to the background, and for the same state to resume when the application is brought to the foreground Solution Use a combination of the UIApplicationDelegate protocol’s messages sent to your application delegate and the notifications sent by iOS to preserve... the Background | 6 25 Figure 12-2 A local notification delivered while our app is running When the application is running or even in the background (has not been terminated yet), iOS will call the application:didReceiveLocalNotification: method of our application delegate to let our application know a local notification has been delivered to us If the user is inside the application, iOS will not do anything... audio files in the background is not implicitly or explicitly asking iOS for extra execution time 632 | Chapter 12: Multitasking 12 .5 Handling Location Changes in the Background Problem You are writing an application whose main functionality is processing location changes, using Core Location You want the application to retrieve the iOS device location changes even if the application is sent to the background... processing iOS has to do to deliver new locations to our application Depending on the version of iOS Simulator that you are testing your applications with and also the settings of your network connection and many other factors which affect this process, background location processing might not work for you Please test your applications, including the source code in this recipe, on a real device 12 .5 Handling... button, iOS will relaunch our application and the user will see a screen similar to that shown in Figure 12 -5 Figure 12 -5 A local notification waking up the terminated app So, you can visually see how local notifications work When our application is running in the foreground or the background, iOS will deliver the local notification through the application:didReceiveLocalNotification: delegate method... empty iOS application (an application with just one window and no code written for it) is run on an iOS device with support for multitasking for the first time (not from the background), the following UIApplicationDelegate messages will be sent to your app delegate, in this order: 1 application:didFinishLaunchingWithOptions: 2 applicationDidBecomeActive: If the user presses the Home button on her iOS. .. implementations of these methods in the implementation file of our app delegate: #import "Saving_and_Loading_the_State_of_Multitasking _iOS_ AppsAppDelegate.h" @implementation Saving_and_Loading_the_State_of_Multitasking _iOS_ AppsAppDelegate 12.6 Saving and Loading the State of Multitasking iOS Apps | 637 @synthesize window = _window; - (void) saveUserScore{ /* Save the user score here */ } - (void) saveLevelToDisk{... switches her iOS device’s language from English to Spanish in the Settings page of the device NSUserDefaultsDidChangeNotification This notification is fired when the user changes the application’s settings in the Settings page of the iOS device (if any setting is provided to the user) UIDeviceBatteryStateDidChangeNotification This notification gets sent whenever the state of the battery of the iOS device... beginBackgroundTaskWithExpirationHandler: instance method of UIAppli cation to borrow some time from iOS The backgroundTimeRemaining property of UIAp plication contains the number of seconds the application has to finish its job If the application doesn’t finish the long-running task before this time expires, iOS will terminate the application Every call to the beginBackgroundTaskWithExpirationHandler: method . (second and third generations), provided that the iOS on these devices has been updated to iOS 4.0 or iOS 5. Furthermore, a device could have iOS 5. 0 or later installed on it, but the under- lying. depending on the iOS devices it targets, can be run and executed on a variety of devices on different operating systems. For instance, if you compile your application with iOS SDK 5. 0 and your deployment. synthesize our video URL property: #import "Editing_Videos_on_an _iOS_ DeviceViewController.h" @implementation Editing_Videos_on_an _iOS_ DeviceViewController @synthesize videoURLToEdit; The next

Ngày đăng: 13/08/2014, 18:20

TỪ KHÓA LIÊN QUAN