Электронная библиотека » Вандад Нахавандипур » » онлайн чтение - страница 41


  • Текст добавлен: 14 июля 2014, 12:45


Автор книги: Вандад Нахавандипур


Жанр: Зарубежная компьютерная литература, Зарубежная литература


сообщить о неприемлемом содержимом

Текущая страница: 41 (всего у книги 59 страниц)

Шрифт:
- 100% +
См. также

Разделы 12.1 и 12.2.

12.5. Удаление файлов и каталогов
Постановка задачи

Вы создали на диске ряд файлов и/или каталогов, и они вам больше не нужны. Вы хотите их удалить.

Решение

Используйте один из двух методов экземпляра, removeItemAtPath: error: или removeItemAtURL: error:, относящихся к классу NSFileManager. Первый метод принимает путь как строку, а второй – как URL.

Обсуждение

Пожалуй, удаление файлов и каталогов – одна из простейших операций, которые можно совершать в файловом менеджере. В iOS нужно обязательно помнить о том, где вы храните ваши файлы и каталоги, а когда хранить их больше не требуется – избавляться от файлов и каталогов. Например, создадим пять текстовых файлов в каталоге tmp/text, а когда закончим работу с ними – удалим эти файлы. Тем временем мы успеем перечислить содержимое каталога по состоянию до и после удаления. Будем делать перечень лишь для того, чтобы убедиться, что все работает правильно. Как вы помните, на момент установки приложения каталог tmp/ существует, а каталог tmp/text – нет. Поэтому для начала потребуется создать второй каталог. Как только закончим работу с файлами, удалим и сам каталог:


/* Создаем каталог по заданному пути */

– (void) createFolder:(NSString *)paramPath{

NSError *error = nil;

if ([self.fileManager createDirectoryAtPath: paramPath

withIntermediateDirectories: YES

attributes: nil

error:&error] == NO){

NSLog(@"Failed to create folder %@. Error = %@",

paramPath,

error);

}

}


/* Создаем пять файлов с расширением. txt в заданном каталоге, называем

их 1.txt, 2.txt и т. д. */

– (void) createFilesInFolder:(NSString *)paramPath{


/* Создаем 10 файлов */

for (NSUInteger counter = 0; counter < 5; counter++){

NSString *fileName = [NSString stringWithFormat:@"%lu.txt",

(unsigned long)counter+1];

NSString *path = [paramPath stringByAppendingPathComponent: fileName];

NSString *fileContents = [NSString stringWithFormat:@"Some text"];

NSError *error = nil;

if ([fileContents writeToFile: path

atomically: YES

encoding: NSUTF8StringEncoding

error:&error] == NO){

NSLog(@"Failed to save file to %@. Error = %@", path, error);

}

}


}


/* Перечисляем все файлы/каталоги, расположенные по заданному пути */

– (void) enumerateFilesInFolder:(NSString *)paramPath{


NSError *error = nil;

NSArray *contents = [self.fileManager contentsOfDirectoryAtPath: paramPath

error:&error];


if ([contents count] > 0 &&

error == nil){

NSLog(@"Contents of path %@ = n%@", paramPath, contents);

}

else if ([contents count] == 0 &&

error == nil){

NSLog(@"Contents of path %@ is empty!", paramPath);

}

else {

NSLog(@"Failed to enumerate path %@. Error = %@", paramPath, error);

}


}


/* Удаляем все файлы/каталоги по заданному пути */

– (void) deleteFilesInFolder:(NSString *)paramPath{


NSError *error = nil;

NSArray *contents = [self.fileManager contentsOfDirectoryAtPath: paramPath

error:&error];


if (error == nil){

error = nil;

for (NSString *fileName in contents){

/* У нас есть имя файла, но, чтобы удалить этот файл,

нужен полный путь к нему */

NSString *filePath = [paramPath

stringByAppendingPathComponent: fileName];

if ([self.fileManager removeItemAtPath: filePath

error:&error] == NO){

NSLog(@"Failed to remove item at path %@. Error = %@",

fileName,

error);

}

}

} else {

NSLog(@"Failed to enumerate path %@. Error = %@", paramPath, error);

}


}


/* Удаляем каталог, к которому ведет заданный путь*/

– (void) deleteFolder:(NSString *)paramPath{

NSError *error = nil;

if ([self.fileManager removeItemAtPath: paramPath error:&error] == NO){

NSLog(@"Failed to remove path %@. Error = %@", paramPath, error);

}

}

Не забывайте: свойство fileManager, которое мы используем в различных методах делегата нашего приложения, – это свойство самого делегата приложения, определяемое следующим образом:

#import «AppDelegate.h»


@interface AppDelegate ()

@property (nonatomic, strong) NSFileManager *fileManager;

@end


@implementation AppDelegate


<# Здесь находится остаток кода делегата приложения #>


В коде из этого примера объединено немало концепций, изученных в этой главе, – от перечисления до создания и удаления файлов. Все это вы здесь найдете. Как видите, с момента начала разработки приложения мы выполняем шесть основных задач, для каждой из которых существуют собственные методы.

1. Создание каталога tmp/txt. Мы знаем, что каталог tmp создается в iOS для каждого приложения, но подкаталог txt на момент установки приложения отсутствует.

2. Создание пяти файлов в каталоге tmp/txt.

3. Перечисление всех файлов в каталоге tmp/txt. Эту операцию нужно выполнить лишь для того, чтобы убедиться, что мы успешно создали в этом каталоге все пять файлов.

4. Удаление всех созданных файлов – собственно, именно эта операция интересовала нас в данном разделе.

5. Повторное перечисление файлов в каталоге tmp/txt. Эту операцию мы выполняем для того, чтобы убедиться, что механизм удаления сработал правильно.

6. Удаление каталога tmp/txt, ведь он нам больше не нужен. Повторюсь: обязательно учитывайте, какие файлы и каталоги вы создаете на диске. Дисковое пространство на дороге не валяется! Поэтому, если какие-то файлы или каталоги вам больше не нужны, обязательно их удаляйте.

См. также

Раздел 12.2.

12.6. Сохранение объектов в файлах
Постановка задачи

Вы добавили в ваш проект новый класс и теперь хотите сохранить этот объект на диск в виде файла, а потом в случае необходимости считать этот файл с диска.

Решение

Убедитесь, что ваш класс соответствует протоколу NSCoding, и реализуйте все необходимые методы данного протокола. Не волнуйтесь, я все подробно объясню в подразделе «Обсуждение» данного раздела.

Обсуждение

В iOS SDK есть два очень удобных класса, предназначенных именно для этой цели. Процесс, который будет описан в этом разделе, в программировании называется «маршалинг». Вот эти классы.

• NSKeyedArchiver – класс, позволяющий архивировать или сохранять содержимое объекта или дерева объектов по ключам. Каждое значение в классе, скажем каждое свойство, может быть сохранено в архиве с применением ключа, выбранного программистом. Вы получаете архивный файл (далее мы обсудим этот момент подробнее) и просто сохраняете ваши значения с ключами, которые выбраны вами же. Точно как в словаре!

• NSKeyedUnarchiver – этот класс работает совершенно противоположным образом. Он просто дает вам неархивированный словарь и предлагает считать значения в свойства вашего объекта.

Для обеспечения работы класса-архиватора и класса-деархиватора необходимо гарантировать, что те объекты, архивацию и деархивацию которых вы запрашиваете, соответствуют протоколу NSCoding. Начнем с простого класса Person. Вот заголовок этого класса:


#import <Foundation/Foundation.h>

@interface Person: NSObject <NSCoding>


@property (nonatomic, copy) NSString *firstName;

@property (nonatomic, copy) NSString *lastName;


@end


Теперь, если вы не напишете никакого кода реализации для этого класса и попытаетесь скомпилировать имеющийся код, то компилятор начнет забрасывать вас предупреждениями, сводящимися к следующему: класс не соответствует протоколу NSCoding и не реализует необходимые методы этого протокола. Вот какие методы нам потребуется реализовать:

• (void)encodeWithCoder:(NSCoder *)aCoder – от этого метода мы получаем сущность-кодировщик. Кодировщик используется точно так же, как словарь. Просто храните в нем значения с ключами на ваш выбор;

• (instancetype)initWithCoder:(NSCoder *)aDecoder; – этот метод вызывается в вашем классе всякий раз, когда вы пытаетесь разархивировать класс с помощью NSKeyedUnarchiver. Просто считывайте значения их экземпляра NSCoder, передаваемого этому методу.

Итак, учитывая сказанное, реализуем наш класс:


#import «Person.h»


NSString *const kFirstNameKey = @"FirstNameKey";

NSString *const kLastNameKey = @"LastNameKey";


@implementation Person


– (void)encodeWithCoder:(NSCoder *)aCoder{

[aCoder encodeObject: self.firstName forKey: kFirstNameKey];

[aCoder encodeObject: self.lastName forKey: kLastNameKey];

}


– (instancetype)initWithCoder:(NSCoder *)aDecoder{

self = [super init];

if (self!= nil){

_firstName = [aDecoder decodeObjectForKey: kFirstNameKey];

_lastName = [aDecoder decodeObjectForKey: kLastNameKey];

}

return self;

}


@end


Как видите, мы работаем с экземпляром класса NSCoder практически так же, как и со словарем. Разница заключается в том, что вместо словарного метода setValue: forKey: мы пользуемся encodeObject: forKey:, а вместо словарного метода objectForKey: задействуем decodeObjectForKey:. Отличия от словарей минимальны.

Итак, с этим классом все понятно. Теперь реализуем механизм архивации и деархивации, пользуясь двумя вышеупомянутыми классами. Мы собираемся сначала инстанцировать объект типа Person, затем заархивировать его, убрать из памяти, потом считать обратно из файла и убедиться, что разархивированное значение совпадает с тем, которое мы изначально записали в класс. Все это мы реализуем в делегате приложения, поскольку там это будет сделать проще всего:


#import «AppDelegate.h»

#import «Person.h»


@implementation AppDelegate


– (BOOL) application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{


/* Определяем имя и фамилию, которые собираемся задать в объекте */

NSString *const kFirstName = @"Steven";

NSString *const kLastName = @"Jobs";


/* Определяем, где хотим заархивировать объект */

NSString *filePath = [NSTemporaryDirectory()

stringByAppendingPathComponent:@"steveJobs.txt"];


/* Инстанцируем объект */

Person *steveJobs = [[Person alloc] init];

steveJobs.firstName = kFirstName;

steveJobs.lastName = kLastName;


/* Архивируем объект в файл */

[NSKeyedArchiver archiveRootObject: steveJobs toFile: filePath];


/* Теперь разархивируем этот же класс в другой объект */

Person *cloneOfSteveJobs =

[NSKeyedUnarchiver unarchiveObjectWithFile: filePath];


/* Проверяем, совпадают ли имя и фамилия в разархивированном объекте

с именем и фамилией, которые находились в ранее архивированном объекте */

if ([cloneOfSteveJobs.firstName isEqualToString: kFirstName] &&

[cloneOfSteveJobs.lastName isEqualToString: kLastName]){

NSLog(@"Unarchiving worked");

} else {

NSLog(@"Could not read the same values back. Oh no!");

}


/* Временный файл нам больше не нужен, удаляем его */

NSFileManager *fileManager = [[NSFileManager alloc] init];

[fileManager removeItemAtPath: filePath error: nil];


self.window = [[UIWindow alloc]

initWithFrame: [[UIScreen mainScreen] bounds]];

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];

return YES;

}


Итак, при архивации просто используется метод класса archiveRootObject: toFile, относящийся к классу NSKeyedArchiver. Этот метод принимает объект и файл, в котором должно быть сохранено содержимое. Все просто. А если нужно разархивировать информацию? Не сложнее архивации. Нам просто нужно найти путь к заархивированному файлу, передать его методу класса unarchiveObjectWithFile:, относящемуся к классу NSKeyedUnarchiver. Всю остальную работу класс выполнит за вас.

См. также

Раздел 12.1.

Глава 13. Камера и библиотека фотографий

13.0. Введение

Большинство устройств с операционной системой iOS, допустим iPhone, оборудованы камерами. У самого нового iPhone две камеры, у других моделей может быть всего по одной. Некоторые устройства с операционной системой iOS не оснащены камерами. Класс UIImagePickerController позволяет программисту отображать для пользователя привычный интерфейс Camera и предлагать сделать снимок или записать видео. Фотографии или видеозаписи, выполненные с помощью класса UIImagePickerController, становятся доступны программисту.

В этой главе будет рассказано, как обеспечить пользователю возможность снимать фотографии и записывать видео прямо из приложения, получать доступ к фотографиям и видео, размещенным в библиотеке фотографий (Photo Library) на устройстве с iOS, например на iPod touch или iPad.

В симуляторе iOS интерфейс Camera не поддерживается. Все приложения, в которых требуется применять этот интерфейс, следует тестировать и отлаживать на настоящем устройстве с iOS, которое оборудовано камерой.

В этой главе мы сначала попытаемся определить, имеется ли камера на том устройстве с iOS, где используется наше приложение. Кроме того, вы можете выяснить, позволяет ли камера вам (программисту) делать фотоснимки, записывать видео или доступны обе эти функции. Для этого необходимо добавить фреймворк MobileCoreServices.framework к целевой сборке. Просто импортируйте его обобщающий фреймворк в ваше приложение, вот так:


#import «AppDelegate.h»

#import <MobileCoreServices/MobileCoreServices.h>


@implementation AppDelegate


<# Остаток вашего кода находится здесь #>


Далее перейдем к изучению других тем, в частности рассмотрим доступ к видео и фотографиям, расположенным в различных альбомах на устройстве с iOS. Речь идет о тех же самых альбомах, в которые можно попасть через приложение Photos (Фотографии), интегрированное в операционную систему iOS.

Но получить доступ к фотографии, находящейся в альбоме, проще, чем к видеозаписи. При работе с фотографиями мы получим адрес снимка и сможем просто загрузить эту информацию об изображении в экземпляр NSData либо прямо в экземпляр UIImage. В аналогичном случае с видео мы не получим адрес, по которому файл находится в файловой системе и с которого можно загрузить нужное видео. Вместо этого получим примерно такой адрес:

assets-library://asset/asset.MOV?id=10000 00004&ext=MOV

При работе с подобными адресами необходимо использовать фреймворк Assets Library (Библиотека ресурсов). Библиотека ресурсов открывает нам доступ к контенту, который обычно предоставляется через приложение Photos (Фотографии). Это, например, фотографии и видеоролики, отснятые пользователем. Кроме того, библиотека ресурсов может применяться для сохранения изображений и видео на устройстве. Потом эти фотографии и ролики будут доступны для библиотеки фотографий (Photo Library), а также других приложений, которым требуется доступ к этому контенту.

Чтобы все коды из этой главы правильно компилировались, убедитесь, что фреймворки Assets Library и Mobile Core Services включены во все ваши файлы с исходным кодом. Для этого можно импортировать заголовочные файлы в файлы с исходным кодом. Предполагается, что вы работаете с последней версией компилятора LLVM, в котором поддерживается работа с модулями:


#import «AppDelegate.h»

#import <MobileCoreServices/MobileCoreServices.h>

#import <AssetsLibrary/AssetsLibrary.h>


@implementation AppDelegate


<# Остаток вашего кода находится здесь #>


Чтобы все коды из этой главы правильно компилировались, выполните следующие шаги – так вы добавите в ваш проект фреймворк Assets Library.

1. В Xcode щелкните на ярлыке проекта.

2. Выберите цель, к которой вы хотите добавить фреймворк.

3. В верхней части интерфейса выберите Build Phases (Этапы сборки).

4. Нажмите кнопку + в нижнем левом углу раздела Link Binaries with Libraries (Связать двоичные файлы с библиотеками).

5. Выберите из списка фреймворк MobileCoreServices.framework.

6. Нажмите Add (Добавить).


Чтобы получить доступ к данным ресурса, имея ссылку на этот ресурс, выполните следующие шаги.

1. Выделите и инициализируйте объект типа ALAssetsLibrary. Объект из библиотеки ресурсов предоставляет специальную перемычку (Bridge), обеспечивающую доступ к тем видеороликам и фотографиям, которые доступны для приложения Photos (Фотографии).

2. Для доступа к ресурсу воспользуйтесь методом экземпляра assetForURL: resultBlock: failureBlock, относящимся к объекту библиотеки ресурсов (выделение и инициализация этого объекта были выполнены на шаге 1). Ресурс может представлять собой изображение, видео или любой другой объект, который Apple потенциально может добавить в библиотеку фотографий. Этот метод работает с блоковыми объектами. Подробнее о блоковых объектах и GCD рассказано в главе 7.

3. Высвободите тот объект библиотеки ресурсов, который был выделен и инициализирован на шаге 1.

На этом этапе у вас может возникнуть вопрос: как же именно я получаю доступ к данным ресурса? Параметр 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.");

} 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;

}


Вот результаты запуска данного приложения на новом iPhone:


The front camera is available. // передняя камера доступна

The front camera is not equipped with a flash // передняя камера

// не оснащена функцией вспышки

The rear camera is available. // задняя камера доступна

The rear camera is equipped with a flash // задняя камера оснащена

, // функцией вспышки

The camera supports taking photos. // камера позволяет делать

, // фотоснимки

The camera supports shooting videos. // камера позволяет

// записывать видео

Вот вывод того же кода при запуске на симуляторе iPhone:

The front camera is not available. // передняя камера недоступна

The rear camera is not available. // задняя камера недоступна

The camera does not support taking photos // камера не поддерживает съемку фотографий

The camera does not support shooting videos // камера не поддерживает съемку видео


Страницы книги >> Предыдущая | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | Следующая
  • 0 Оценок: 0

Правообладателям!

Это произведение, предположительно, находится в статусе 'public domain'. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.


Популярные книги за неделю


Рекомендации