目录
1.UIViewController
2.UINavigationController
3.UIImagePickController
4.UITableViewController
5.ABPeoplePickNavigationController
6.MFMailCompseViewContriller
1.视图控制器概述
1.视图控制器是UIViewController类或其子类对象,每个视图控制器都负责管理一个视图层次结构,包含创建视图层次结构中的视图并处理相关用户事件,以及将整个视图层次结构添加到应用窗口。MVC架构模式:模型-视图-控制器,UIViewController就是MVC模式中的C。
2.UIViewController可以管理一屏的内容,如果说UIWindow是一副画的画框,那么UIViewController就是画框中植入的一张画布。我们并不建议将所有的视图对象或子视图都直接置于UIWindow对象中,因为UIWindow对象是唯一的,如果要想改变用户界面就会非常的麻烦。如果使用UIViewController来管理用户界面的话,在切换用户界面时只需要更换一个视图控制器就可以了。它定义了一系列和生命周期相关的方法
** UIViewController视图控制器的生命周期:**
屏幕快照 2017-04-13 上午9.59.16.png 屏幕快照 2017-04-13 上午9.59.50.png扩展:iOS应用程序的生命周期( http://www.jianshu.com/p/aa50e5350852 )
iOS程序执行顺序和UIViewController 的生命周期https://www.jianshu.com/p/d60b388b19f5
视图控制器加载:
20150704084850885.jpeg视图控制器收到内存警告:
20150704084904755.jpeg 屏幕快照 2017-04-13 上午10.01.30.png 屏幕快照 2017-04-13 上午10.01.42.png- 如何将UIViewController和UIWindow关联:
#import "CDRootViewController.h"
@interface CDRootViewController () {
NSArray *infos;
}
@end
@implementation CDRootViewController
- (instancetype)init {
if(self = [super init]) {
infos = @[@"Hello, world!", @"How are you?", @"Nice to meet you!", @"See you!", @"Good night!"];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 将直接放在AppDelegate中的代码转移到视图控制器中
// 将原来直接放到UIWindow上的视图添加到视图控制器的视图中
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGPoint centerPoint = CGPointMake(screenRect.size.width / 2.0, screenRect.size.height / 2.0);
UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
centerPoint.y -= 50;
infoLabel.center = centerPoint;
infoLabel.textAlignment = NSTextAlignmentCenter;
infoLabel.font = [UIFont systemFontOfSize:36];
infoLabel.text = infos[0];
infoLabel.textColor = [UIColor redColor];
infoLabel.tag = 101;
infoLabel.adjustsFontSizeToFitWidth = YES;
UIButton *okButton = [UIButton buttonWithType:UIButtonTypeSystem];
okButton.frame = CGRectMake(0, 0, 80, 40);
centerPoint.y += 100;
okButton.center = centerPoint;
[okButton setTitle:@"OK" forState:UIControlStateNormal];
okButton.layer.borderColor = [UIColor blackColor].CGColor;
okButton.layer.borderWidth = 1;
okButton.layer.cornerRadius = 5;
okButton.layer.shadowColor = [UIColor yellowColor].CGColor;
okButton.layer.shadowRadius = 10;
[okButton addTarget:self action:@selector(okButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:infoLabel];
[self.view addSubview:okButton];
}
- (void) okButtonClicked {
UILabel *infoLabel = (id)[self.view viewWithTag:101];
int randomIndex = arc4random() % [infos count];
infoLabel.text = infos[randomIndex];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[UIView commitAnimations];
}
@end
AppDelegate的代码如下所示:
#import "AppDelegate.h"
#import "CDRootViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
// 创建视图控制器对象
CDRootViewController *rvc = [[CDRootViewController alloc] init];
// 将视图控制器设置为窗口的根视图控制器
self.window.rootViewController = rvc;
[self.window makeKeyAndVisible];
return YES;
}
@end
2. UINavigationController(导航栏)
1.导航栏简介
20150704234502935.png我们使用模态方式切换视图控制器是有一些局限性的,一种更为优雅的切换视图的方式是通过导航的方式进行切换。导航视图控制器是一个特殊的容器视图控制器,它可以维护有明确层次关系的视图之间的切换。我们可以打开模拟器或者你的iPhone看看设置功能,这里就是一个典型的对导航视图控制器的应用,如下图所示。很明显,导航视图控制器维护了一个栈结构,这是一种先进后出(FILO)的结构,我们将一个一个的视图压入栈中,当我们想返回的时候就可以依次出栈。
2.创建导航控制器
- -initWithRootViewController::在创建导航控制器时指定根视图控制器
- -initWithNavigationBarClass:toobarClass::用指定的导航条创建导航视图控制器
3.控制器的入栈和出栈
- -pushViewController:animated:方法:将一个视图控制器压入栈中
- -popViewControllerAnimated:方法:从栈中弹出一个视图控制器
- -popToRootViewControllerAnimated:方法:从栈中直接弹出根视图控制器
- -popToViewController:animated:方法:从栈中弹出指定的视图控制器
20150824074059298.png
可以通过UINavigationController的viewControllers属性获得其栈中保存的所有视图控制器;topViewController可以获得栈顶的视图控制器。
4.UINavigationBar
一个导航视图控制器通常是由以下几个部分构成的:
20150824074114313.png
5.导航条半透明以及相关坐标计算
导航视图控制器会维持一个导航条(UINavigationBar),这个导航条被所有的视图控制器共享,可以通过UINavigationController对象navigationBar属性获得导航条,再通过下面的属性设置其半透明效果,注意对导航条的设置将对所有的视图控制器生效。
-
translucent属性:设置导航条是否半透明,默认值是YES。对此属性的设置会影响到坐标的计算,因为导航条有44点的高度。例如在视图控制控制器中放置一个按钮,其frame属性的第二个参数设置为100,那么在设置半透明为YES和NO的情况下按钮的呈现效果如下图所示。可以看出设置半透明后的按钮坐标计算是以窗口顶端为参考系的,而不透明的时候按钮坐标是相对于导航条的,相差了44个点。
20150705100648644.png
20150705100659936.png
6.设置背景图片
- -setBackgroundImage:forBarMetrics:
- -setBackgroundImage:forBarPosition:barMetrics:
说明:UIBarPostion和UIBarMetrics都是枚举类型,前者表示导航栏的位置;后者表示导航栏的外观。前者可能的取值包括:UIBarPositionAny(不指定位置)、UIBarPositionBottom(位于视图底部)、UIBarPositionTop(位于视图顶部)和UIBarPositionTopAttached(位于屏幕顶部同时也在其视图的顶部);后者可能的取值包括:UIBarMetricsDefault(设备默认的外观)、UIBarMetricsCompact(手机尺寸的外观)等。
7.隐藏和显示导航条
- navigationBarHidden属性:是否隐藏导航控制栏
8.UINavigationItem
通过视图控制器的navigationItem属性可以获得和视图控制器对应的导航栏项,该属性是只读的,但是通过它的子属性可以对UINavigationItem进行定制。可以定制的内容包括:
- leftBarButtonItem/leftBarButtonItems属性:定制左侧导航项
- rightBarButtonItem/rightBarButtonItems属性:定制右侧导航项
- backBarButtonItem属性:定制返回项
- title属性:导航项的标题
- prompt属性:导航项的提示
- titleView属性:导航项标题视图,该属性可以是任意* UIView及其子类型,因此可以在此随意定制自己想要的东西
说明:由于navigationItem是每个视图持有自己的navigationItem,因此可以为每个视图定制不同的导航项。
- 如果当前视图控制器通过navigationItem设置了leftBarButtonItem,则显示当前视图控制器设置好的leftBarButtonItem;如果当前视图控制器没有设置leftBarButtonItem,且当前视图控制器不是根视图控制器,显示上一层的backBarButtonItem;如果上一层没有指定backBarButtonItem,系统将根据上一层视图控制器的标题自动生成一个返回按钮;如果当前视图控制器没有设置leftBarButtonItem且当前视图控制器是根视图控制器,则左边不显示任何东西。
- 如果当前视图控制器通过navigationItem属性定制了titleView,那么将会显示自定义的titleView,titleView的高度不应该超过导航条的高度;如果当前视图控制器没有定制titleView,系统会根据当前视图控制器的标题或者navigationItem的标题创建一个UILabel来显示此标题;navigationItem的标题优于视图控制器的标题。
- 强调:UINavigationController本身并不显示无需定制,UINavigationBar属于导航控制器(子对象),它使被多个视图共享的,当你切换视图控制器时,导航栏并没有切换,如果需要定制导航视图控制器就需要定制导航栏以及导航栏上的项目UINavigationItem。我们可以让每个视图控制器都有自己的UINavigationItem,并按照自己的意愿来创建它。
下面通过代码对上述内容加以展示:
创建文字和图片UIBarButtonItem
// 重设rightBarButtonItem
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleDone target:self action:@selector(onClick:)];
//重设leftBarButtonItem
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"itemImage1"] landscapeImagePhone:[UIImage imageNamed:@"itemImage2"] style:UIBarButtonItemStyleBordered target:nil action:nil];
创建系统自带的UIBarButtonSystemItem
UIBarButtonItem * item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:nil action:nil];
UIBarButtonItem * item2 = [[UIBarButtonItem alloc] initWithTitle:@"OK" style:UIBarButtonItemStylePlain target:nil action:nil];
// 使用自定义视图,创建barButtonItem
UISwitch * sw = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
[sw addTarget:self action:@selector(pushNextViewController) forControlEvents:UIControlEventValueChanged];
// barButton官方推荐大小是20*20
UIBarButtonItem * item3 = [[UIBarButtonItem alloc] initWithCustomView:sw];
// 将多个item添加到右侧
self.navigationItem.rightBarButtonItems = @[item1, item2, item3];
定制backBarButtonItem
UIButton *goBackButton = [UIButton buttonWithType:UIButtonTypeSystem];
goBackButton.frame = CGRectMake(10, 10, 60, 40);
[goBackButton addTarget:self action:@selector(goBackButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[goBackButton setTitle:@"滚蛋" forState:UIControlStateNormal];
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:goBackButton];
self.navigationItem.leftBarButtonItem = barItem;
9.UIToolbar
每个导航控制器,还配备了工具条(44坐标高),默认隐藏,可以通过将导航视图控制器的toolBarHidden属性设置为NO使其显示。工具条属于UINavigationController,一个导航控制器,只有一个工具条。工具条上的toolBarItem属于每个视图控制器,每个视图控制器可以单独定制工具条上的每个项。
显示UINavigationController自带的UIToolbar
- toolBarHidden属性:设置为NO可以显示自带的工具条
设置UIToolbar的背景图:
self.navigationController.toolbarHidden = NO;
UIImage *bgImage = [UIImage imageNamed:@"toolBar"];
[navigationController.toolbar setBackgroundImage:bgImage forToolbarPosition:UIBarPositionBottom barMetrics:UIBarMetricsDefault];
[self.navigationController.toolbar setTintColor:[UIColor whiteColor]];
向UIToolbar中增加UIBarButtonItem:
UIBarButtonItem * item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil];
UIBarButtonItem * item2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:nil action:nil];
UIBarButtonItem * item3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:nil action:nil];
UIBarButtonItem * spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
self.toolbarItems = @[item1, spaceItem, item2, spaceItem, item3];
10.UIAppearance
UIAppearrance的作用:
从iOS 5开始,UIKit中提供了一个叫做UIAppearance的协议,通过该协议可以轻松的统一你的界面,它提供如下两个方法:
- (id)appearance:通过它可以修改所有的指定类型的视图的UI
- (id)appearanceWhenContainedIn:(Class <>)ContainerClass,…:可以指定要修改的类型包括哪些
修改导航样式:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setBackgroundImage:myNavBarButtonBackgroundImage forState:state barMetrics:metrics];
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], [UIPopoverController class], nil] setBackgroundImage:myPopoverNavBarButtonBackgroundImage forState:state barMetrics:metrics];
[[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil] setBackgroundImage:myToolbarButtonBackgroundImage forState:state barMetrics:metrics];
[[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], [UIPopoverController class], nil] setBackgroundImage:myPopoverToolbarButtonBackgroundImage forState:state barMetrics:metrics];
3. UIImagePickController
UIImagePickerController是iOS系统提供的和系统的相册和相机交互的一个类,可以用来获取相册的照片,也可以调用系统的相机拍摄照片或者视频。该类的继承结构是:
UIImagePickerController-->UINavigationController-->UIViewController-->UIResponder-->NSObject
- **官方文档中对于该类的说明是: **
该类只支持竖屏模式,为了保证该类被原样使用,它不支持子类,并且它的视图层次是私有的不能被修改,只支持自定义cameraOverlayView属性来展示更多信息以及和用户的交互。- 由于该类继承自UINavgationController,所以在使用过程中一般实现UIImagePickerControllerDelegate和UINavigationControllerDelegate这两个代理,可以利用navgation的push 和pop操作自定义界面实现更复杂的交互效果
属性
@property(nullable,nonatomic,weak) id <UINavigationControllerDelegate, UIImagePickerControllerDelegate> delegate;
该对象的代理需要实现UINavigationControllerDelegate和UIImagePickerControllerDelegate协议,nullable是xcode6.3之后引入的nullability annotations特性,主要用于在OC和swift之间的转换。这一特性主要包含两个新的类型注释nullable和nonnull,用于表示对象是否可以是NULL或nil
@property(nonatomic) UIImagePickerControllerSourceType sourceType; // default value is UIImagePickerControllerSourceTypePhotoLibrary.
sourceType用于指定要访问的系统的媒体类型。UIImagePickerControllerSourceType支持以下3种枚举类型,默认值是图片库
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
UIImagePickerControllerSourceTypePhotoLibrary,
UIImagePickerControllerSourceTypeCamera,
UIImagePickerControllerSourceTypeSavedPhotosAlbum
};
PhotoLibrary代表系统照片应用对应的相薄,包含照片流和其它自定义的相册,PhotosAlbum则对应系统照片应用的照片,包含用设备拍摄的所有照片流。Camera则代表相机的摄像头。
@property(nonatomic,copy) NSArray<NSString *> *mediaTypes;
mediaTypes用于设置相机支持的功能,拍照或者是视频,返回值类型可以是kUTTypeMovie,kUTTypeImage
@property(nonatomic) BOOL showsCameraControls NS_AVAILABLE_IOS(3_1);
@property(nonatomic) BOOL allowsEditing NS_AVAILABLE_IOS(3_1); // replacement for -allowsImageEditing; default value is NO.
@property(nonatomic) BOOL allowsImageEditing NS_DEPRECATED_IOS(2_0, 3_1);
showsCameraControls用于指定拍照时下方的工具栏是否显示,allowImageEditing在iOS3.1就已废弃,取而代之的是allowEditing,表示拍完照片或者从相册选完照片后,是否跳转到编辑模式对图片裁剪,只有在showsCameraControls为YES时才有效果。
@property(nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode NS_AVAILABLE_IOS(4_0); // default is UIImagePickerControllerCameraCaptureModePhoto
@property(nonatomic) UIImagePickerControllerCameraDevice cameraDevice NS_AVAILABLE_IOS(4_0); // default is UIImagePickerControllerCameraDeviceRear
@property(nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode
@property(nullable, nonatomic,strong) __kindof UIView *cameraOverlayView NS_AVAILABLE_IOS(3_1); // set a view to overlay the preview view.
@property(nonatomic) CGAffineTransform cameraViewTransform NS_AVAILABLE_IOS(3_1); // set the transform of the preview view.
当sourceType是camera的时候,这几个属性有限,否则抛出异常。cameraCaptureMode捕捉模式指定的是相机是拍摄照片还是视频,它的枚举类型如下:
NS_ENUM(NSInteger, UIImagePickerControllerCameraCaptureMode) {
UIImagePickerControllerCameraCaptureModePhoto,//photo
UIImagePickerControllerCameraCaptureModeVideo//video
};
cameraDevice指定拍摄的摄像头位置,是使用前置摄像头还是后置摄像头,它的枚举类型有:
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
UIImagePickerControllerCameraDeviceRear,
UIImagePickerControllerCameraDeviceFront
};
cameraFlashMode用于指定闪光灯模式,它的枚举类型如下:
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {
UIImagePickerControllerCameraFlashModeOff = -1,
UIImagePickerControllerCameraFlashModeAuto = 0,
UIImagePickerControllerCameraFlashModeOn = 1
};
cameraViewTransform该结构体可以用于指定拍摄时View的一些形变属性,如旋转缩放等。
当showsCameraControls为NO,系统的工具栏隐藏时,我们可以自定义背景View赋值给cameraOverlayView添加到拍摄时的预览视图之上。
@property(nonatomic) NSTimeInterval videoMaximumDuration NS_AVAILABLE_IOS(3_1); // default value is 10 minutes.
@property(nonatomic) UIImagePickerControllerQualityType videoQuality NS_AVAILABLE_IOS(3_1);
videoMaximumDuration用于设置视频拍摄模式下最大拍摄时长,默认值是10分钟。 videoQuality表示拍摄的视频质量设置,默认是Medium即表示中等质量。 videoQuality支持的枚举类型如下:
typedef NS_ENUM(NSInteger, UIImagePickerControllerQualityType) {
UIImagePickerControllerQualityTypeHigh = 0, // 高清模式
UIImagePickerControllerQualityTypeMedium = 1, //中等质量,适于WIFI传播
UIImagePickerControllerQualityTypeLow = 2, //低等质量,适于蜂窝网络传输
UIImagePickerControllerQualityType640x480 NS_ENUM_AVAILABLE_IOS(4_0) = 3, // VGA 质量
UIImagePickerControllerQualityTypeIFrame1280x720 NS_ENUM_AVAILABLE_IOS(5_0) = 4,//1280*720的分辨率
UIImagePickerControllerQualityTypeIFrame960x540 NS_ENUM_AVAILABLE_IOS(5_0) = 5,//960*540分辨率
};
类方法:
@interface UIImagePickerController : UINavigationController <NSCoding>
+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType; // returns YES if source is available (i.e. camera present)
+ (nullable NSArray<NSString *> *)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType; // returns array of available media types (i.e. kUTTypeImage)
+ (BOOL)isCameraDeviceAvailable:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0); // returns YES if camera device is available
+ (BOOL)isFlashAvailableForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0); // returns YES if camera device supports flash and torch.
+ (nullable NSArray<NSNumber *> *)availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0);
isSourceTypeAvailable用于判断当前设备是否支持指定的sourceType,可以是照片库/相册/相机.
isCameraDeviceAvailable判断当前设备是否支持前置摄像头或者后置摄像头
isFlashAvailableForCameraDevice是否支持前置摄像头闪光灯或者后置摄像头闪光灯
availableMediaTypesForSourceType方法返回所特定的媒体如相册/图片库/相机所支持的媒体类型数组,元素值可以是kUTTypeImage类型或者kUTTypeMovie类型的静态字符串,所以是NSString类型的数组
availableCaptureModesForCameraDevice返回特定的摄像头(前置摄像头/后置摄像头)所支持的拍摄模式数值数组,元素值可以是UIImagePickerControllerCameraCaptureMode枚举里面的video或者photo,所以是NSNumber类型的数组
对象方法:
- (void)takePicture NS_AVAILABLE_IOS(3_1);
- (BOOL)startVideoCapture NS_AVAILABLE_IOS(4_0);
- (void)stopVideoCapture NS_AVAILABLE_IOS(4_0);
takePicture可以用来实现照片的连续拍摄,需要自己自定义拍摄的背景视图来赋值给cameraOverlayView ,结合自定义overlayView实现多张照片的采集,在收到代理的didFinishPickingMediaWithInfo方法之后可以启动额外的捕捉。
startVideoCapture用来判断当前是否可以开始录制视频,当视频正在拍摄中,设备不支持视频拍摄,磁盘空间不足等情况,该方法会返回NO.该方法结合自定义overlayView可以拍摄多部视频
stopVideoCapture当你调用此方法停止视频拍摄时,它会调用代理的imagePickerController:didFinishPickingMediaWithInfo:方法
代理方法:
@protocol UIImagePickerControllerDelegate<NSObject>
@optional
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo NS_DEPRECATED_IOS(2_0, 3_0);
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
@end
imagePickerController:didFinishPickingImage:editingInfo:在iOS3.0中已废弃,不再使用。当用户取消选取的内容时会调用DidCancel方法,默认实现销毁弹出的视图。当完成内容的选取时会调用didFinishPickingMediaWithInfo方法,默认info字典的key值可以是以下类型:
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaType; //指定用户选择的媒体类型
UIKIT_EXTERN NSString *const UIImagePickerControllerOriginalImage; // 原始图片
UIKIT_EXTERN NSString *const UIImagePickerControllerEditedImage; // 修改后的图片
UIKIT_EXTERN NSString *const UIImagePickerControllerCropRect; // 裁剪尺寸
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaURL; // 媒体的URL
UIKIT_EXTERN NSString *const UIImagePickerControllerReferenceURL NS_AVAILABLE_IOS(4_1); // 原件的URL
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaMetadata //当数据来源是相机的时候获取到的静态图像元数据,可以使用phtoho框架进行处理
C函数(保存照片或视频):
UIKIT_EXTERN void UIImageWriteToSavedPhotosAlbum(UIImage *image, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo);
UIKIT_EXTERN BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath) NS_AVAILABLE_IOS(3_1);
UIKIT_EXTERN void UISaveVideoAtPathToSavedPhotosAlbum(NSString *videoPath, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo) NS_AVAILABLE_IOS(3_1);
UIImageWriteToSavedPhotosAlbum用来保存照片到相册,seletor应该设置为- (void)image:(UIImage )image didFinishSavingWithError:(NSError )error contextInfo:(void )contextInfo;当照片保存到相册完成时,会调用该方法通知你。
UIVideoAtPathIsCompatibleWithSavedPhotosAlbum会返回布尔类型的值判断该路径下的视频能否保存到相册,视频需要先存储到沙盒文件再保存到相册,而照片是可以直接从代理完成的回调info字典里面获取到。
UISaveVideoAtPathToSavedPhotosAlbum用来保存视频到相册,seletor应该设置为- (void)video:(NSString )videoPath didFinishSavingWithError:(NSError )error contextInfo:(void )contextInfo;当视频保存到相册或出错时会调用该方法通知你。
这三个方法一般是在代理的完成方法didFinishPickingMediaWithInfo里面配合使用
关于编辑照片界面的英文,可以在info.plist设置Localized resources can be mixed 的值为YES就可以转换为你当前系统的语言。下面是关于使用UIImagePickerConreoller来上传头像,照片多选以及拍摄视频的一个Demo
4. UITableViewController
概述:表格视图控制器UITableViewController类继承自UIViewController类,极大地简化了创建UITableView的过程。
UITableViewController负责处理表格布局,并使用一个UITableView实例对其进行填充。可设置此控制器的窗体以支持任意导航栏或工具栏;可以通过tableView实例变量访问表格视图;默认情况下使用UITableViewController创建的tableView是充满全屏的,如果需要用到tableView是不充满全屏的话,我们应该使用UIViewController。
重要提示:手工代码创建UITableViewController的子类时,如果定义loadView方法,则确保调用其超类的实现[super loadView]。只有这样才能保证表格视图的正确设置以及在子类中添加定制功能。若是使用IB创建UITableViewController,则不必向loadView添加任何调用。
注意:手动修改继承的控制器是不行的(就是比如,你创建控制器的时候是继承UIViewController,然后你手动修改成了UITableViewController,是没效果的),必须创建的时候就继承Table控制器
以例子讲解:
新建一个项目,然后新建一个继承自UITableViewController的类,具体情况如下图所示:
在前面的篇幅中,我们知道,要实现tableView的相关功能,必须设置dataSource和delegate,以及遵守UITableViewDataSource和UITableViewDelegate协议,并且实现协议中的相关方法。来到ESTableViewController.m文件,我们可以看到,文件中已经列出了数据源的相关方法。实际上,设置数据源和代理,遵守相关协议,这些步骤,UITableViewController内部已经帮我们做好了,而我们新建的ESTableViewController类又是继承自UITableViewController的,因此相关步骤可以省去。
按住command键,在Xcode的编辑区域中点击UITableViewController,进入其头文件,我们可以清楚的看到,它已经遵守了相关协议,而且内部已经拥有一个tableView属性了。我们接下来要做的,就是为tableView提供数据,实现相应的方法就可以了。
1012450-b6097012cfcd1e99.png我们先来简单的实现以下数据源的相关方法:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 4;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 创建cell
UITableViewCell *cell = [[UITableViewCell alloc] init];
// 设置cell数据
cell.textLabel.text = [NSString stringWithFormat:@"%@ - %zd", [self class], indexPath.row];
return cell;
}
来到storyboard,往编辑区域拖一个UITableViewController控制器,如下图所示:
1012450-b53812da2a7a99e6.png选中UITableViewController控制器,勾选"Is Initial View Controller",然后我们会发现UITableViewController左边多出一个灰色的箭头,如下图所示:
1012450-35fb1d6388faf486.png点击"Show the Identity Inspector",在class后面的输入框中输入你新建的类名ESTableViewController,完成类型绑定。具体操作如下图所示:
1012450-c7cb7422503476cf.png我们来运行一下程序,看看效果:
1012450-3ea1cd9d7362f49b.gif从运行结果来看,数据并没有明显的分组,这不是我们程序出了问题,而是分组样式默认为Plain,我们只需将分组样式改为Grouped,即可呈现我们想要的结果。另外,项目目录中的ViewController文件,以及storyboard中的View Controller其实已经没什么用了,我们完全可以将它们删掉。
有一个细节需要说明一下。从前面的学习中我们知道,要在UIViewController里面实现UITableView的功能,需要手动创建一个tableView属性,并且UIViewController里面本身就有一个view属性,这两个属性肯定是不同的。而通过今天的学习,我们知道,UITableViewController继承自UIViewController,所以它里面自然有一个view属性,重要的是,UITableViewController本身就自带一个tableView属性,那么这两个属性是否也不同呢?我们可以打印一下他们的地址查看一下:
1012450-08ccd1078d5c895f.png从打印结果来看,在UITableViewController中,view属性和tableView属性是同一个东西,它们引用的是同一个对象。
补充:在日常的开发中,我们可能会有如图一样的需求,需要让UITableViewController的分割线距离屏幕两边各10pt或者20pt等等,只需要设置cell的separatorInset属性即可,如 :cell.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);如果我们需要让UITableViewController的分割线距离屏幕两边各为0时。 cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0),设置完之后,发现分割线距离左边并不是为0,只需要再设置layoutMargins属性即可,两者缺一不可: cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0) cell.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0)
5. ABPeoplePickNavigationController
和通讯录中联系人相关的应用iPhone提供了两个框架:AddressBook.framework和AddressBookUI.framework,使用这两个框架我们可以在程序中访问并显示iPhone数据库中的联系人信息
具体介绍:
1.AddressBookUI显示部分
屏幕快照 2017-04-13 下午2.09.09.png例子:
- (IBAction)showPicker:(id)sender {
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
}
屏幕快照 2017-04-13 下午2.09.28.png
例子:
(a)示例:
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
// assigning control back to the main controller
[picker dismissModalViewControllerAnimated:YES];
}
(b)示例:
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
//获取联系人姓名
name.text = (NSString*)ABRecordCopyCompositeName(person);
//获取联系人电话
ABMutableMultiValueRef phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSMutableArray *phones = [[NSMutableArray alloc] init];
int i;
for (i = 0; i < ABMultiValueGetCount(phoneMulti); i++)
{
NSString *aPhone = [(NSString*)ABMultiValueCopyValueAtIndex(phoneMulti, i) autorelease];
NSString *aLabel = [(NSString*)ABMultiValueCopyLabelAtIndex(phoneMulti, i) autorelease];
NSLog(@"PhoneLabel:%@ Phone#:%@",aLabel,aPhone);
if([aLabel isEqualToString:@"_$!<Mobile>!$_"])
{
[phones addObject:aPhone];
}
}
phoneNo.text=@"";
if([phones count]>0)
{
NSString *mobileNo = [phones objectAtIndex:0];
phoneNo.text = mobileNo;
//NSLog(mobileNo);
}
//获取联系人邮箱
ABMutableMultiValueRef emailMulti = ABRecordCopyValue(person, kABPersonEmailProperty);
NSMutableArray *emails = [[NSMutableArray alloc] init];
for (i = 0;i < ABMultiValueGetCount(emailMulti); i++)
{
NSString *emailAdress = [(NSString*)ABMultiValueCopyValueAtIndex(emailMulti, i) autorelease];
[emails addObject:emailAdress];
}
email.text=@"";
if([emails count]>0)
{
NSString *emailFirst=[emails objectAtIndex:0];
email.text = emailFirst;
//NSLog(emailFirst);
}
[peoplePicker dismissModalViewControllerAnimated:YES];
return NO;
}
(c)示例
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier {
return NO;
}
2.AddressBook部分
屏幕快照 2017-04-13 下午2.16.01.png相关链接:http://www.cnblogs.com/pretty-guy/p/4253646.html
6. MFMailCompseViewContriller
简介:允许你创建用户可以直接在程序中定制邮件消息
网友评论