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、一个更简单的方法是通过设置一个确定的字体,来进行适配

 

posted @ 2017-11-16 09:51  Frank9098  阅读(101)  评论(0)    收藏  举报