Вандад Нахавандипур - iOS. Приемы программирования
На этом этапе у вас может возникнуть вопрос: как же именно я получаю доступ к данным ресурса? Параметр resultBlock метода экземпляра assetForURL: resultBlock: failureBlock, относящегося к объекту библиотеки ресурсов, должен указывать на блоковый объект, принимающий единственный параметр типа ALAsset. ALAsset — это класс, предоставляемый в библиотеке ресурсов, он инкапсулирует (включает в себя) ресурс, доступный для Photos (Фотографии) или любого другого приложения iOS, пытающегося использовать этот ресурс. Тема сохранения фотоснимков и видеороликов в библиотеке фотографий более подробно рассмотрена в разделах 13.4 и 13.5. О получении фотографий и видео из библиотеки фотографий и библиотеки ресурсов подробнее рассказано в разделах 13.6 и 13.7.
13.1. Обнаружение и испытание камеры
Постановка задачи
Требуется узнать, есть ли камера на том устройстве с iOS, где работает ваше приложение, и можете ли вы получить доступ к этой камере. Это очень важный момент, который нужно проверить, прежде чем приступать к работе с камерой. Ведь нельзя исключить вероятность того, что ваше приложение будет использоваться и на каких-то устройствах, не оснащенных камерой.
Решение
Применяйте метод класса isSourceTypeAvailable:, относящийся к классу UIImagePickerController, со значением UIImagePickerControllerSourceTypeCamera следующим образом:
— (BOOL) isCameraAvailable{
return [UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera];
}
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
if ([self isCameraAvailable]){
NSLog(@"Camera is available.");
} else {
NSLog(@"Camera is not available.");
}
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Обсуждение
Прежде чем попытаться отобразить для пользователя экземпляр UIImagePickerController, позволяющий делать фотоснимки или записывать видео, нужно проверить, поддерживается ли на устройстве этот интерфейс. Метод класса isSourceTypeAvailable: позволяет определить три источника данных:
• камеру — для этого данному методу сообщается значение UIImagePickerControllerSourceTypeCamera;
• библиотеку фотографий — для этого данному методу сообщается значение UIImagePickerControllerSourceTypePhotoLibrary. В результате включается обзор корневого каталога в директории Photos на устройстве;
• каталог с фотографиями, отснятыми с камеры данного устройства (Camera Roll), — в таком случае метод получает значение UIImagePickerControllerSourceTypeSavedPhotosAlbum.
Если вы собираетесь проверить доступность любой из этих функций на устройстве с iOS, нужно передать описанные значения методу класса isSourceTypeAvailable:, относящемуся к классу UIImagePickerController, и лишь потом попробовать отобразить для пользователя соответствующий интерфейс.
Теперь можно воспользоваться методами класса isSourceTypeAvailable: и availableMediaTypesForSourceType:, относящимися к классу UIImagePickerController, чтобы для начала определить, доступен ли источник медийной информации (например, камера, библиотека фотографий и т. д.). Если источник имеется, определим, какие типы медиаинформации (например, изображения или видео) в нем предоставляются:
— (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) doesCameraSupportShootingVideos{
return [self cameraSupportsMedia:(__bridge NSString *)kUTTypeMovie
sourceType: UIImagePickerControllerSourceTypeCamera];
}
— (BOOL) doesCameraSupportTakingPhotos{
return [self cameraSupportsMedia:(__bridge NSString *)kUTTypeImage
sourceType: UIImagePickerControllerSourceTypeCamera];
}
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
if ([self doesCameraSupportTakingPhotos]){
NSLog(@"The camera supports taking photos.");
} else {
NSLog(@"The camera does not support taking photos");
}
if ([self doesCameraSupportShootingVideos]){
NSLog(@"The camera supports shooting videos.");
} else {
NSLog(@"The camera does not support shooting videos.");
}
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Мы приводим типы значений kUTTypeMovie и kUTTypeImage к NSString с помощью __bridge (как было рассказано в разделе 1.18). Это объясняется тем, что два вышеупомянутых значения относятся к типу CFStringRef и нам нужно получить их представление в виде NSString. Чтобы упростить работу статического анализатора и компилятора и не получать от компилятора лишних сообщений, лучше выполнить такое приведение типов.
На некоторых устройствах с iOS может быть установлена не одна камера. Например, их может быть две — передняя и задняя. Чтобы определить, доступны ли эти камеры, воспользуйтесь методом класса isCameraDeviceAvailable:, относящимся к классу UIImagePickerController:
— (BOOL) isFrontCameraAvailable{
return [UIImagePickerController
isCameraDeviceAvailable: UIImagePickerControllerCameraDeviceFront];
}
— (BOOL) isRearCameraAvailable{
return [UIImagePickerController
isCameraDeviceAvailable: UIImagePickerControllerCameraDeviceRear];
}
Если вызвать эти методы на не самом новом iPhone, где отсутствует задняя камера, то можно заметить, что метод isFrontCameraAvailable возвращает NO, а метод isRearCameraAvailable — YES. При запуске данного кода на iPhone, оснащенном как передней, так и задней камерами, оба метода вернут YES, поскольку на iPhone 4 имеются две камеры — спереди и сзади.
Если в вашем приложении недостаточно просто определить, какая камера имеется на устройстве, можно получить и другие настройки, воспользовавшись классом UIImagePickerController. Одна из этих настроек позволяет узнать, есть ли на камере данного устройства функция вспышки. Метод класса isFlashAvailableForCameraDevice:, относящийся к классу UIImagePickerController, применяется, чтобы выяснить, на какой камере доступна функция вспышки — передней или задней. Не забывайте также, что метод класса isFlashAvailableForCameraDevice:, относящийся к классу UIImagePickerController, сначала проверяет доступность запрошенной камеры, а уже потом проверяется доступность функции вспышки на этой камере. Поэтому методы, которые мы здесь реализуем, можно будет запускать и на устройствах, лишенных передней или задней камеры, без необходимости предварительной проверки доступности камеры:
— (BOOL) isFlashAvailableOnFrontCamera{
return [UIImagePickerController isFlashAvailableForCameraDevice:
UIImagePickerControllerCameraDeviceFront];
}
— (BOOL) isFlashAvailableOnRearCamera{
return [UIImagePickerController isFlashAvailableForCameraDevice:
UIImagePickerControllerCameraDeviceRear];
}
Теперь, если воспользоваться всеми методами, написанными в этом разделе, и протестировать их, например, в делегате нашего приложения, мы сможем увидеть результаты на различных устройствах:
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
if ([self isFrontCameraAvailable]){
NSLog(@"The front camera is available.");
if ([self isFlashAvailableOnFrontCamera]){
NSLog(@"The front camera is equipped with a flash");
} else {
NSLog(@"The front camera is not equipped with a flash");
}
} else {
NSLog(@"The front camera is not available.");
}
if ([self isRearCameraAvailable]){
NSLog(@"The rear camera is available.");
if ([self isFlashAvailableOnRearCamera]){
NSLog(@"The rear camera is equipped with a flash");
} else {
NSLog(@"The rear camera is not equipped with a flash");
}
} else {
NSLog(@"The rear camera is not available.");
}
if ([self doesCameraSupportTakingPhotos]){
NSLog(@"The camera supports taking photos.");
} else {
NSLog(@"The camera does not support taking photos");
}
if ([self doesCameraSupportShootingVideos]){
NSLog(@"The camera supports shooting videos.");