002-iOS9新特性
一、3D Touch
1.简介
在iphone6s问世之后,很多果粉都争先要体验3D Touch给用户带来的额外维度上的交互,这个设计之所以叫做3D Touch,其原理上是增加了一个压力的感触,通过区分轻按和重按来进行不同的用户交互
2.使用方法
iOS9为我们提供了两种标签:静态标签(通过info.plist配置)、动态标签(通过代码添加)
1)静态标签

UIApplicationShortcutItems的数组:这个数组中添加的元素就是对应的静态标签
a.必填项
UIApplicationShortcutItemType 这个键值设置一个快捷通道类型的字符串
UIApplicationShortcutItemTitle 这个键值设置标签的标题
b.选填项
UIApplicationShortcutItemSubtitle 设置标签的副标题
UIApplicationShortcutItemIconType 设置标签Icon类型
UIApplicationShortcutItemIconFile 设置标签的Icon文件
UIApplicationShortcutItemUserInfo 设置信息字典(用于传值)
2)动态标签

a.UIApplicationShortcutItem类
1 #pragma mark - 初始化方法 2 - (instancetype)init; 3 - (instancetype)initWithType:(NSString *)type localizedTitle:(NSString *)localizedTitle localizedSubtitle:(nullable NSString *)localizedSubtitle icon:(nullable UIApplicationShortcutIcon *)icon userInfo:(nullable NSDictionary *)userInfo; 4 - (instancetype)initWithType:(NSString *)type localizedTitle:(NSString *)localizedTitle; 5 6 #pragma mark - 属性设置 7 @property (nonatomic, copy, readonly) NSString *type; // 类型 8 @property (nonatomic, copy, readonly) NSString *localizedTitle; // 标题 9 @property (nullable, nonatomic, copy, readonly) NSString *localizedSubtitle; // 子标题 10 @property (nullable, nonatomic, copy, readonly) UIApplicationShortcutIcon *icon; // 图标 11 @property (nullable, nonatomic, copy, readonly) NSDictionary<NSString *, id <NSSecureCoding>> *userInfo; // 用于传值的参数
b.UIMutableApplicationShortcutItem类
1 @property (nonatomic, copy) NSString *type; // 类型 2 @property (nonatomic, copy) NSString *localizedTitle; // 标题 3 @property (nullable, nonatomic, copy) NSString *localizedSubtitle; // 子标题 4 @property (nullable, nonatomic, copy) UIApplicationShortcutIcon *icon; // 图标 5 @property (nullable, nonatomic, copy) NSDictionary<NSString *, id <NSSecureCoding>> *userInfo; // 用于传值的参数
c.UIApplicationShortcutIcon类
1 #pragma mark - 初始化方法 2 // UIApplicationShortcutIconType 3 // UIApplicationShortcutIconTypeCompose // 编辑的图标 4 // UIApplicationShortcutIconTypePlay // 播放图标 5 // UIApplicationShortcutIconTypePause // 暂停图标 6 // UIApplicationShortcutIconTypeAdd // 添加图标 7 // UIApplicationShortcutIconTypeLocation // 定位图标 8 // UIApplicationShortcutIconTypeSearch // 搜索图标 9 // UIApplicationShortcutIconTypeShare // 分享图标 10 + (instancetype)iconWithType:(UIApplicationShortcutIconType)type; 11 + (instancetype)iconWithTemplateImageName:(NSString *)templateImageName;
3)响应标签的方法
1 // 类似推送,当我们点击标签进入应用程序时,也可以进行一些操作,我们可以看到,在AppDelegate中增加了一个方法 2 // 当我们通过标签进入app时,就会在AppDelegate中调用这样一个回调,我们可以获取shortcutItem的信息进行相关逻辑操作 3 - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler; 4 5 // 这里有一点需要注意:我们在app的入口函数也需要做一些处理 6 // 也需要进行一下判断,在launchOptions中有UIApplicationLaunchOptionsShortcutItemKey这样一个键,通过它,我们可以区别是否是从标签进入的app,如果是则处理结束逻辑后,返回NO,防止处理逻辑被反复回调 7 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
4)代码实例
a.AppDelegate.m文件
1 #import "AppDelegate.h" 2 3 @interface AppDelegate () 4 5 @end 6 7 @implementation AppDelegate 8 9 // 这里有一点需要注意:我们在app的入口函数也需要做一些处理 10 // 也需要进行一下判断,在launchOptions中有UIApplicationLaunchOptionsShortcutItemKey这样一个键,通过它,我们可以区别是否是从标签进入的app,如果是则处理结束逻辑后,返回NO,防止处理逻辑被反复回调 11 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 12 { 13 if (launchOptions[UIApplicationLaunchOptionsShortcutItemKey]) { 14 return NO; 15 } 16 return YES; 17 } 18 19 // 类似推送,当我们点击标签进入应用程序时,也可以进行一些操作,我们可以看到,在AppDelegate中增加了一个方法 20 // 当我们通过标签进入app时,就会在AppDelegate中调用这样一个回调,我们可以获取shortcutItem的信息进行相关逻辑操作 21 - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler 22 { 23 NSLog(@"type = %@, localizedTitle = %@, localizedSubtitle = %@", shortcutItem.type, shortcutItem.localizedTitle, shortcutItem.localizedSubtitle); 24 } 25 26 @end
b.ViewController.m文件
1 #import "ViewController.h" 2 3 @interface ViewController () 4 5 @end 6 7 @implementation ViewController 8 9 - (void)viewDidLoad 10 { 11 [super viewDidLoad]; 12 13 // 创建 14 UIApplicationShortcutIcon *icon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypePlay]; 15 UIApplicationShortcutItem *item = [[UIApplicationShortcutItem alloc]initWithType:@"two" localizedTitle:@"第二个标签" localizedSubtitle:@"看我哦" icon:icon userInfo:nil]; 16 // 添加 17 [UIApplication sharedApplication].shortcutItems = @[item]; 18 } 19 20 @end

运行效果:

注意:
1、快捷标签最多可以创建四个,包括静态的和动态的。
2、每个标签的题目和icon最多两行,多出的会用...省略
二、App传输安全
APP Transport Security——加密传输方式
随着ios9的推出和Xcode的升级,apple将默认开发者使用https的传输方式,相比http的传输协议,这无疑会增加一些安全性,对于开发者而言,一下子将http协议全部升级为https协议,不是一件容易的事,我们可以通过Xcode的一些配置,使其支持http的传输协议
首先,在项目的Info.plist中加入NSAppTransportSecurity这个键,类型为Dictionary,在字典中添加一对键值,键为Boolen类型的NSAllowsArbitraryLoads,值为YES,如下:

三、堆叠视图UIStackView
1.简介
随着autolayout的推广开来,更多的app开始使用自动布局的方式来构建自己的UI系统,autolayout配合storyboard和一些第三方的框架,对于创建约束来说,已经十分方便,但是对于一些动态的线性布局的视图,我们需要手动添加的约束不仅非常多,而且如果我们需要插入或者移除其中的一些UI元素的时候,我们又要做大量的修改约束的工作,UIStackView正好可以解决这样的问题
2.UIStackView的属性设置和方法
1)布局设置
1 @property(nonatomic) UILayoutConstraintAxis axis; 2 UILayoutConstraintAxisHorizontal // 水平布局 3 UILayoutConstraintAxisVertical // 竖直布局
2)对齐模式
1 @property(nonatomic) UIStackViewAlignment alignment; 2 UIStackViewAlignmentFill // 水平布局时为高度充满,竖直布局时为宽度充满 3 UIStackViewAlignmentLeading // 前边对其 4 UIStackViewAlignmentTop = UIStackViewAlignmentLeading // 顶部对其 5 UIStackViewAlignmentFirstBaseline // 第一个控件文字的基线对其 水平布局有效 6 UIStackViewAlignmentCenter // 中心对其 7 UIStackViewAlignmentTrailing // 后边对其 8 UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing // 底部对其 9 UIStackViewAlignmentLastBaseline // 最后一个控件文字的基线对其,水平布局有效
3)排列方式
1 @property(nonatomic) UIStackViewDistribution distribution; 2 UIStackViewDistributionFill // 充满,当只有一个控件时可以使用 3 UIStackViewDistributionFillEqually // 平分充满,每个控件占据相同尺寸排列充满 4 UIStackViewDistributionFillProportionally // 会优先按照约束的尺寸进行排列,如果没有充满,会拉伸最后一个排列的控件充满 5 UIStackViewDistributionEqualSpacing // 等间距排列 6 UIStackViewDistributionEqualCentering // 中心距离相等
4)其他属性设置
1 @property(nonatomic) CGFloat spacing; // 设置最小间距 2 @property(nonatomic,getter=isBaselineRelativeArrangement) BOOL baselineRelativeArrangement; // 设置布局时是否参照基线 3 @property(nonatomic,getter=isLayoutMarginsRelativeArrangement) BOOL layoutMarginsRelativeArrangement; // 设置布局时是否以控件的LayoutMargins为标准,默认为NO,是以控件的bounds为标准
5)方法&只读属性
1 #pragma mark - 初始化方法,通过数组传入被管理的视图 2 - (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views; 3 #pragma mark - 添加一个视图进行管理 4 - (void)addArrangedSubview:(UIView *)view; 5 #pragma mark - 移除一个被管理的视图 6 - (void)removeArrangedSubview:(UIView *)view; 7 #pragma mark - 在指定位置插入一个被管理的视图 8 - (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex; 9 10 #pragma mark - 获取被管理的所有视图 11 @property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *arrangedSubviews;
3.代码创建UIStackView
1 #import "ViewController.h" 2 #import "Masonry.h" // 第三方布局 3 4 @interface ViewController () 5 6 @end 7 8 @implementation ViewController 9 10 - (void)viewDidLoad 11 { 12 [super viewDidLoad]; 13 14 [self initUI]; // 初始化UI 15 [self initUIStackView]; // UIStackView的初始化 16 } 17 18 #pragma mark - 初始化UI 19 - (void)initUI 20 { 21 self.view.backgroundColor = [UIColor lightGrayColor]; 22 23 // addBtn 24 UIButton *addBtn = [UIButton buttonWithType:UIButtonTypeSystem]; 25 addBtn.frame = CGRectMake(40, 80, 80, 45); 26 [addBtn setTitle:@"添加View" forState:UIControlStateNormal]; 27 addBtn.tintColor = [UIColor whiteColor]; 28 addBtn.backgroundColor = [UIColor redColor]; 29 [addBtn addTarget:self action:@selector(addBtnClick:) forControlEvents:UIControlEventTouchUpInside]; 30 [self.view addSubview:addBtn]; 31 32 // deleteBtn 33 UIButton *deleteBtn = [UIButton buttonWithType:UIButtonTypeSystem]; 34 deleteBtn.frame = CGRectMake(self.view.bounds.size.width - 40 - 80, 80, 80, 45); 35 [deleteBtn setTitle:@"删除View" forState:UIControlStateNormal]; 36 deleteBtn.tintColor = [UIColor whiteColor]; 37 deleteBtn.backgroundColor = [UIColor redColor]; 38 [deleteBtn addTarget:self action:@selector(deleteBtnClick:) forControlEvents:UIControlEventTouchUpInside]; 39 [self.view addSubview:deleteBtn]; 40 } 41 42 #pragma mark - UIStackView的初始化 43 - (void)initUIStackView 44 { 45 NSMutableArray *array = [[NSMutableArray alloc] init]; 46 NSArray *colors = @[[UIColor redColor], [UIColor blueColor], [UIColor yellowColor], [UIColor purpleColor], [UIColor orangeColor]]; 47 for (int i = 0 ; i < 5; i++) { 48 UIView * view = [[UIView alloc] init]; 49 view.backgroundColor = colors[i]; 50 view.tag = 10 + i; 51 [array addObject:view]; 52 } 53 UIStackView *stackView = [[UIStackView alloc]initWithArrangedSubviews:array]; 54 stackView.tag = 100; 55 [self.view addSubview:stackView]; 56 // 给stackView添加约束条件 57 // 注意:无论代码还是storyboard,对stackView都必须约束完位置和尺寸 58 [stackView mas_makeConstraints:^(MASConstraintMaker *make) { 59 make.centerX.equalTo(self.view.mas_centerX); 60 make.centerY.equalTo(self.view.mas_centerY); 61 make.leading.equalTo(self.view.mas_leading).offset(20); 62 make.trailing.equalTo(self.view.mas_trailing).offset(-20); 63 make.size.height.equalTo(@100); 64 }]; 65 // 属性设置 66 // 注意:属性设置这里如果设置其他属性,可能还会需要对stackView中的view也需要添加一些布局 67 stackView.axis = UILayoutConstraintAxisHorizontal; // 水平布局 68 stackView.distribution = UIStackViewDistributionFillEqually; // 等宽充满 69 stackView.alignment = UIStackViewAlignmentFill; // 高度充满 70 } 71 72 #pragma mark - 点击事件 73 // 1.添加View 74 - (void)addBtnClick:(UIButton *)sender 75 { 76 UIStackView *stackView = [self.view viewWithTag:100]; 77 UIView * newView = [[UIView alloc] init]; 78 newView.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1]; 79 [stackView addArrangedSubview:newView]; 80 // 在添加view的时候会有动画效果 81 [stackView addArrangedSubview:newView]; 82 [UIView animateWithDuration:1 animations:^{ 83 [stackView layoutIfNeeded]; 84 }]; 85 } 86 // 2.删除View 87 - (void)deleteBtnClick:(UIButton *)sender 88 { 89 UIStackView *stackView = [self.view viewWithTag:100]; 90 UIView *view = [self.view viewWithTag:10]; 91 // 移除view 92 [stackView removeArrangedSubview:view]; 93 } 94 95 @end

4.storyboard中创建UIStackView

四、BitCode的配置
BitCode是app的一种中间形式,我们可以在提交app时提交app的Bitcode形式,如此一来,apple会对我们的app进行二次优化,在用户下载时根据所需再进行编译打包。在Xocde7中,新建的项目是默认开启BitCode的,如果我们用Xcode7编译提交应用,这里有需要注意适配的地方
如果要支持BitCode,需要保证所有的SDK都支持BitCode,如果要更新旧的SDK,只需要在Xcode7上开启BitCode重新制作一遍即可。
如果不能使所有SDK都支持BitCode,可以在项目中关闭BitCode,在building Setting中搜索BitCode,将enable设置为NO,如下:

五、label默认字体不同产生的Bug
适配注意点:
1、可以通过动态计算来获取label的宽度,进行设置label的宽度
2、一个更简单的方法是通过设置一个确定的字体,来进行适配

浙公网安备 33010602011771号