iOS开发:相机与照片库应用及应用本地化指南
相机与照片库应用开发
在开发一个允许用户使用相机拍照、拍摄视频,或者从照片库中选择内容并显示在屏幕上的应用时,需要进行一系列的操作。
1. 处理用户取消图像选择器的情况
当用户取消图像选择器时,需要确保正确关闭选择器。以下是
imagePickerControllerDidCancel:
方法的基本实现:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
2. 设计界面
-
创建项目
:在Xcode中使用单视图应用模板创建一个名为
Camera的新项目。 -
添加出口和协议
:在
ViewController.m的类扩展中添加以下协议和属性:
#import "ViewController.h"
@interface ViewController ()
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIButton *takePictureButton;
@end
由于
UIImagePickerController
是
UINavigationController
的子类,所以需要同时遵循这两个协议。
- 添加动作方法 :添加两个动作方法,目前先创建空实现:
- (IBAction)shootPictureOrVideo:(UIButton *)sender {
}
- (IBAction)selectExistingPictureOrVideo:( UIButton *)sender {
}
-
在Interface Builder中编辑GUI
:
-
从库中拖两个按钮到视图中,上面的按钮标题设为
New Photo or Video,下面的按钮标题设为Pick from Library。 -
拖一个图像视图到按钮上方,将其背景设为黑色,模式设为
Aspect Fit。 -
建立连接:从视图控制器图标控制拖动到图像视图选择
imageView出口,再拖动到New Photo or Video按钮选择takePictureButton出口。 -
连接事件:选择
New Photo or Video按钮,从Touch Up Inside事件拖动到视图控制器选择shootPictureOrVideo:动作;对Pick from Library按钮进行同样操作,选择selectExistingPictureOrVideo:动作。 -
添加自动布局约束:
-
从
Pick from Library按钮控制拖动到主视图,选择Leading Space to Container Margin、Trailing Space to Container Margin和Bottom Space to Bottom Layout Guide。 -
从
New Photo or Video按钮控制拖动到Pick from Library按钮,选择Vertical Spacing。 -
从
New Photo or Video按钮控制拖动到主视图,选择Leading Space to Container Margin和Trailing Space to Container Margin。 -
从
New Photo or Video按钮控制拖动到图像视图,选择Vertical Spacing。 -
从图像视图控制拖动到主视图,选择
Leading Space to Container Margin、Trailing Space to Container Margin和Top Space to Top Layout Guide。 -
同时选中两个按钮,点击
Pin按钮,勾选Width并添加约束。
-
从
-
从库中拖两个按钮到视图中,上面的按钮标题设为
3. 实现相机视图控制器
-
添加属性和导入头文件
:在
ViewController.m中添加以下内容:
#import "ViewController.h"
#import <MediaPlayer/MediaPlayer.h>
#import <MobileCoreServices/UTCoreTypes.h>
@interface ViewController ()
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIButton *takePictureButton;
@property (strong, nonatomic) MPMoviePlayerController *moviePlayerController;
@property (strong, nonatomic) UIImage *image;
@property (strong, nonatomic) NSURL *movieURL;
@property (copy, nonatomic) NSString *lastChosenMediaType;
@end
-
增强
viewDidLoad和viewDidAppear:方法 :
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if (![UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera]) {
self.takePictureButton.hidden = YES;
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self updateDisplay];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-
实现实用方法
:
-
updateDisplay方法 :
-
- (void)updateDisplay {
if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeImage]) {
self.imageView.image = self.image;
self.imageView.hidden = NO;
self.moviePlayerController.view.hidden = YES;
} else if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeMovie]) {
if (self.moviePlayerController == nil) {
self.moviePlayerController = [[MPMoviePlayerController alloc]
initWithContentURL:self.movieURL];
UIView *movieView = self.moviePlayerController.view;
movieView.frame = self.imageView.frame;
movieView.clipsToBounds = YES;
[self.view addSubview:movieView];
[self setMoviePlayerLayoutConstraints];
} else {
self.moviePlayerController.contentURL = self.movieURL;
}
self.imageView.hidden = YES;
self.moviePlayerController.view.hidden = NO;
[self.moviePlayerController play];
}
}
- **`setMoviePlayerLayoutConstraints` 方法**:
- (void)setMoviePlayerLayoutConstraints {
UIView *moviePlayerView = self.moviePlayerController.view;
UIView *takePictureButton = self.takePictureButton;
moviePlayerView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *views =
NSDictionaryOfVariableBindings(moviePlayerView, takePictureButton);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
@"H:|[moviePlayerView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
@"V:|[moviePlayerView]-0-[takePictureButton]" options:0 metrics:nil
views:views]];
}
- **`pickMediaFromSource:` 方法**:
- (void)pickMediaFromSource:(UIImagePickerControllerSourceType)sourceType {
NSArray *mediaTypes = [UIImagePickerController
availableMediaTypesForSourceType:sourceType];
if ([UIImagePickerController
isSourceTypeAvailable:sourceType] && [mediaTypes count] > 0) {
UIImagePickerController *picker =
[[UIImagePickerController alloc] init];
picker.mediaTypes = mediaTypes;
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = sourceType;
[self presentViewController:picker animated:YES completion:NULL];
} else {
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Error accessing media"
message:@"Unsupported media source."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES
completion:nil];
}
}
- 实现动作方法 :
- (IBAction)shootPictureOrVideo:(id)sender {
[self pickMediaFromSource:UIImagePickerControllerSourceTypeCamera];
}
- (IBAction)selectExistingPictureOrVideo:(id)sender {
[self pickMediaFromSource:UIImagePickerControllerSourceTypePhotoLibrary];
}
- 实现委托方法 :
#pragma mark - Image Picker Controller delegate methods
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.lastChosenMediaType = info[UIImagePickerControllerMediaType];
if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeImage]) {
self.image = info[UIImagePickerControllerEditedImage];
} else if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeMovie]) {
self.movieURL = info[UIImagePickerControllerMediaURL];
}
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
完成上述步骤后,编译并运行应用。在模拟器上只能从照片库选择内容,而在真机上可以拍照、拍摄视频,并且首次访问用户照片时会请求权限。
应用本地化
随着iOS设备在全球超过90个国家可用,应用的潜在市场非常大。iOS提供了强大的本地化架构,允许将应用轻松翻译成多种语言甚至同一语言的不同方言。
1. 本地化架构概述
- 非本地化应用 :运行时应用的所有文本将以开发者的语言(开发基础语言)呈现。
-
本地化应用
:开发者为每个支持的语言在应用包中创建子目录(本地化文件夹),文件夹名以
.lproj结尾,包含翻译后的资源。
2. 资源加载规则
当本地化应用需要加载资源时,会检查用户设置的语言和地区,按以下顺序查找本地化文件夹:
1. 先查找语言/地区匹配的文件夹,如用户选择法语(瑞士),先找
fr-CH.lproj
。
2. 若未找到,使用语言的三字母ISO代码查找,如
fre-CH
或
fra-CH
。
3. 若仍未找到,只查找语言匹配的文件夹,如
fr.lproj
。
4. 若都未找到,使用开发基础语言的资源。
如果有多个匹配的本地化文件夹,会优先查找更具体的匹配。例如,用户选择瑞士法语,优先查找
fr-CH.lproj
,若未找到资源再查找
fr.lproj
。
3. 本地化建议
只对受语言或地区影响的资源进行本地化。例如,没有文字且含义通用的图像无需本地化。
通过以上步骤,开发者可以开发出功能丰富的相机与照片库应用,并实现应用的本地化,以满足全球用户的需求。
iOS开发:相机与照片库应用及应用本地化指南(续)
相机与照片库应用开发总结
为了更清晰地展示相机与照片库应用开发的流程,我们可以用以下流程图表示:
graph TD;
A[创建项目] --> B[设计界面];
B --> C[实现相机视图控制器];
C --> D[编译运行];
B --> B1[添加出口和协议];
B --> B2[添加动作方法];
B --> B3[编辑GUI];
B --> B4[添加自动布局约束];
C --> C1[添加属性和导入头文件];
C --> C2[增强视图方法];
C --> C3[实现实用方法];
C --> C4[实现动作方法];
C --> C5[实现委托方法];
下面我们通过一个表格总结开发过程中的关键代码和功能:
| 功能模块 | 代码示例 | 功能说明 |
| — | — | — |
| 处理用户取消选择器 |
objc - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:NULL]; }
| 当用户取消图像选择器时,关闭选择器 |
| 视图控制器协议和属性 |
objc @interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate> @property (weak, nonatomic) IBOutlet UIImageView *imageView; @property (weak, nonatomic) IBOutlet UIButton *takePictureButton; @end
| 遵循必要协议,定义出口属性 |
| 动作方法 |
objc - (IBAction)shootPictureOrVideo:(id)sender { [self pickMediaFromSource:UIImagePickerControllerSourceTypeCamera]; } - (IBAction)selectExistingPictureOrVideo:(id)sender { [self pickMediaFromSource:UIImagePickerControllerSourceTypePhotoLibrary]; }
| 调用
pickMediaFromSource:
方法选择媒体源 |
| 实用方法 -
updateDisplay
|
objc - (void)updateDisplay { if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeImage]) { self.imageView.image = self.image; self.imageView.hidden = NO; self.moviePlayerController.view.hidden = YES; } else if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeMovie]) { // ... } }
| 根据选择的媒体类型更新显示内容 |
| 实用方法 -
setMoviePlayerLayoutConstraints
|
objc - (void)setMoviePlayerLayoutConstraints { UIView *moviePlayerView = self.moviePlayerController.view; UIView *takePictureButton = self.takePictureButton; moviePlayerView.translatesAutoresizingMaskIntoConstraints = NO; NSDictionary *views = NSDictionaryOfVariableBindings(moviePlayerView, takePictureButton); [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat: @"H:|[moviePlayerView]|" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat: @"V:|[moviePlayerView]-0-[takePictureButton]" options:0 metrics:nil views:views]]; }
| 设置电影播放器的布局约束 |
| 实用方法 -
pickMediaFromSource:
|
objc - (void)pickMediaFromSource:(UIImagePickerControllerSourceType)sourceType { NSArray *mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType]; if ([UIImagePickerController isSourceTypeAvailable:sourceType] && [mediaTypes count] > 0) { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.mediaTypes = mediaTypes; picker.delegate = self; picker.allowsEditing = YES; picker.sourceType = sourceType; [self presentViewController:picker animated:YES completion:NULL]; } else { // ... } }
| 创建并配置图像选择器,根据源类型选择相机或媒体库 |
| 委托方法 |
objc - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { self.lastChosenMediaType = info[UIImagePickerControllerMediaType]; if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeImage]) { self.image = info[UIImagePickerControllerEditedImage]; } else if ([self.lastChosenMediaType isEqual:(NSString *)kUTTypeMovie]) { self.movieURL = info[UIImagePickerControllerMediaURL]; } [picker dismissViewControllerAnimated:YES completion:NULL]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:NULL]; }
| 处理选择媒体完成和取消选择的情况 |
应用本地化深入探讨
1. 本地化操作步骤
要实现应用的本地化,具体操作步骤如下:
1.
创建本地化文件夹
:在应用包中为每个支持的语言创建子目录,命名以
.lproj
结尾。例如,为英语创建
en.lproj
,为法语创建
fr.lproj
等。
2.
翻译资源
:将应用中受语言影响的资源(如文本、图片中的文字等)翻译成对应语言,并放入相应的本地化文件夹中。
3.
设置支持的语言
:在Xcode项目设置中,添加支持的语言。具体操作如下:
- 打开项目的
Info.plist
文件。
- 找到
Localizations
字段,点击
+
号添加支持的语言。
2. 本地化注意事项
- 资源管理 :确保每个本地化文件夹中的资源与开发基础语言的资源结构一致,避免出现资源缺失或不匹配的问题。
-
动态文本
:对于应用中动态生成的文本,需要使用本地化函数进行处理,以确保在不同语言环境下正确显示。例如,在Objective - C中可以使用
NSLocalizedString函数:
NSString *localizedText = NSLocalizedString(@"Hello", @"Greeting message");
-
日期和时间格式
:不同地区的日期和时间格式可能不同,需要根据用户的地区设置进行调整。可以使用
NSDateFormatter类来处理日期和时间的格式化:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
NSString *formattedDate = [dateFormatter stringFromDate:[NSDate date]];
3. 本地化测试
在完成本地化后,需要进行充分的测试,以确保应用在不同语言和地区环境下都能正常显示和运行。可以通过以下方式进行测试:
-
模拟器测试
:在iOS模拟器中设置不同的语言和地区,运行应用检查显示是否正确。
-
真机测试
:在不同语言和地区设置的真机上运行应用,进行全面的测试。
总结
通过本文的介绍,我们详细了解了iOS相机与照片库应用的开发流程,以及应用本地化的相关知识。在开发相机与照片库应用时,需要注意界面设计、视图控制器的实现和委托方法的处理。而在进行应用本地化时,要遵循资源加载规则,合理选择需要本地化的资源,并进行充分的测试。通过这些步骤,开发者可以开发出功能完善、支持多语言的iOS应用,满足全球用户的需求。
超级会员免费看
12

被折叠的 条评论
为什么被折叠?



