UI总结
文章目录
- 1. UI总结
- 1.1. 1、程序启动后的开始动画
- 1.2. 2、LaunchScreen.xib
- 1.3. 3、给插件添加自定义的提醒方式
- 1.4. 4、给分类添加属性的话,只会生成set和get方法
- 1.5. 5、如何抛出异常
- 1.6. 6、自定义tabBar
- 1.7. 7、手动添加pch文件都项目
- 1.8. 8、load和initialize
- 1.9. 9、 给任意弹出的窗口添加遮盖
- 1.10. 10、loadView、viewDidLoad和viewDidUnLoad
- 1.11. 11、UINavigationBar
- 1.12. 12、九宫格布局UICollectionViewController
- 1.13. 13、运行时 - runtime
- 1.14. 14、自定义系统默认生成的手势
- 1.15. 15、高斯模糊实现
- 1.16. 16、block 循环利用
- 1.17. 16、json文件
- 1.18. 17、控制器的父子关系
- 1.19. 18、UIScrollView使用注意
- 1.20. 19、窗口悬停
- 1.21. 20、const和指针以及数组
UI总结
1、程序启动后的开始动画
程序启动后可以加载一个简单的动画界面来介绍程序或者用户信息。
可以使用一个xib来描述界面。并且如果想在程序加载完成后第一个加载这个xib文件,需要在Appdelegate中手动加载这个xib
// 通过stroyboard启动,跟控制器的view并不会在程序启动完成的时候添加到窗口,属于懒加载范畴 |
- 在xib中如果想给内部子控件添加动画,并且动画和主界面的出现有延迟,需要在以下某个方法中实现。
// 视图添加到窗口时会调用方法didMoveToWindow 再调用didMoveToSuperview |
2、LaunchScreen.xib
- 这个系统自动生成的xib文件在应用启动时会自动加载,可以在里面添加一些控件,但是注意:LaunchScreen比LaunchImage优先级高。
- 设置LaunchImage需要注意,默认模拟器的尺寸跟启动图片有关系。
// 加载类的时候调用 |
3、给插件添加自定义的提醒方式
- 自定义的分类,想让这个方法弹出加载图片提醒
|
把这个方法添加到插件中再次编译运行就可。
打开插件工程,找到配置文件,是一个plist文件,然后添加需要的条目。
4、给分类添加属性的话,只会生成set和get方法
|
5、如何抛出异常
NSInteger count = items.count; // 按钮个数 |
6、自定义tabBar
默认barBar显示的图片高度不能超过44,如果大于44显示出问题,这是可以自定义tabBar。
6.1、新建一个类SLQTabBar,因为tabBar的个数不确定,所以需要外界传入,这里使用模型数组来设置。
// 模仿下UITabBar |
- 6.2、模型数组只需在初始化时添加一次即可,所以使用懒加载方式.
@interfaceSLQTabBar () |
- 6.3、tabBar上是一排按钮排列而成,不过没有高亮状态,只有Normal和selected状态。
- 这个只需要重写 UIButton的一个方法即可。新建一个继承自UIButton的类,重写 setHighlighted 方法
|
- 6.4、每次添加过按钮之后都要对按钮进行布局
- (void)layoutSubviews |
- 6.5、响应按钮点击的话,使用代理传递数据
// 定义 |
- 6.6、具体使用方法,在控制器中设置tabBar
- 添加自定义的tabBar到tabBar,然后将系统生成的按钮删除.
//添加自定义的tabBar到tabBar,然后将系统生成的按钮删除 |
- 移除系统按钮
- (void)viewWillAppear:(BOOL)animated |
- 监听按钮点击
- (void)tabBar:(SLQTabBar *)tabBar didClickButton:(NSInteger)index |
7、手动添加pch文件都项目
pch文件中包含的东西在项目中每个文件中都可以使用。
8、load和initialize
// 当程序一启动的时候就会调用 |
9、 给任意弹出的窗口添加遮盖
这个也比较常见,比如说弹出登陆界面时,程序其他部分都是灰色背景,且不能点击。
可以给程序添加一个灰色的View,而且要显示在所有界面之前,那么可以使用
[UIApplication sharedApplication].keyWindow;
添加到这个窗口上的窗口默认都在最前面。
自定义一个继承自UIView的类,添加两个方法即可。
// 屏幕尺寸 |
10、loadView、viewDidLoad和viewDidUnLoad
作用
- loadView 苹果设计这个方法就是给我们自定义UIViewController的view用的
- viewDidLoad 在创建过控制器的view后,向view中添加其他控件
- viewDidUnLoad 系统发出内存警告时
关系
- 1.第一次访问UIViewController的view时,view为nil,然后就会调用loadView方法创建view
- 2.view创建完毕后会调用viewDidLoad方法进行界面元素的初始化
- 3.当内存警告时,系统可能会释放UIViewController的view,将view赋值为nil,并且调用viewDidUnload方法
- 4.当再次访问UIViewController的view时,view已经在3中被赋值为nil,所以又会调用loadView方法重新创建view
- 5.view被重新创建完毕后,还是会调用viewDidLoad方法进行界面元素的初始化
View的生命周期
11、UINavigationBar
- 所生成的图片都是经过处理的view,为蓝色
- 原始图片
// 默认左右两遍的view都是蓝色的,所以要返回一个原始的图片 |
12、九宫格布局UICollectionViewController
- 创建控制器一定要指定默认的布局样式。
// 加载一个九宫格布局的控制器,必须指定布局样式 |
- 在指定布局时可以设置各种属性
- (instancetype)init |
- 如果想显示控件,那么使用方法和UITableView非常相似。使用代理设置每个CollectionView
// 一共多少组 |
13、运行时 - runtime
- 首先包含头文件,然后使用里面的方法即可
// 运行时对象 |
- 可以看到系统默认在滑动手势时作的一些事情,指定了手势的target和action,可以利用这些方法来自定义自己的手势。
14、自定义系统默认生成的手势
- 1、首先要找到这个手势相关联的属性和方法。因为是私有的,不能直接看到,所以只能通过运行时机制获取属性名
- 先通过运行时机制的一些函数,观察属性名,然后确定在自己要得。
int count = 0; |
- 2、找出属性名并添加手势
// 找到属性名 |
- 3、实现代理方法-只要不是根控制器就使用手势
// UIGestureRecognizerDelegate 代理方法 |
15、高斯模糊实现
- 这个方法是别人封装好的,直接拿来使用即可。
|
16、block 循环利用
// block会把代码里所有强指针全部强引用 |
16、json文件
- 文件中保存的时字典数据
[ |
- 直接当做普通文件读取就行
- (NSMutableArray *)items |
- 关键一句话是使用 NSJSONSerialization 对文件进行解析
NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; |
- 文件中读取的关键字和系统保留字有冲突
- 那么读取时就要进行修正,使用KVC进行字典读取要保证,模型中得属性和字典中元素数量和名称一致,不能有任何差别。
- 现在的问题就是,文件中又一项数据的key是id,这个和系统的保留字id冲突,必须对id进行转换。所以声明属性是大写ID。
@property (strong, nonatomic) NSString *ID; |
- 重写setvalue方法,在方法里进行转换,这个可以应对数量较少的键值对冲突,如果有十几个或者更多,使用起来就很麻烦,要写一堆if语句。
// 因json文件中得字典key 是id,与系统关键字冲突,手动判断再返回正确的值 |
- 更加方便的方法是抽出一个分类,因对更加复杂的情况,如果有10个key和系统关键字重复,这个分类比较好使。
// 快速进行字典转模型 |
- 使用方法,要初入一个冲突的字典
SLQHtmlItem *item = [SLQHtmlItem objectWithDict:dict mapDict:@{@"ID":@"id"}]; |
17、控制器的父子关系
1、控制器父子关系的建立原则
- 如果2个控制器的view是父子关系(不管是直接还是间接的父子关系),那么这2个控制器也应该为父子关系
[self.view addSubview:view];
[self addChildViewController:viewController];
- 如果2个控制器的view是父子关系(不管是直接还是间接的父子关系),那么这2个控制器也应该为父子关系
2、获得所有的子控制器
@property(nonatomic,readonly) NSArray *childViewControllers;
- 3、添加一个子控制器
// ViewController成为了self的子控制器 |
- 4、获得父控制器
@property(nonatomic,readonly) UIViewController *parentViewController;
- 5、将一个控制器从它的父控制器中移除
// 控制器a从它的父控制器中移除
[selfremoveFromParentViewController];
- 6、添加控件到主控件后调用
- (void)didMoveToParentViewController:(UIViewController *)parent |
18、UIScrollView使用注意
- UIScrollView内部子控件添加约束的注意点
- 1、子控件的尺寸不能通过UIScrollView来计算,可以考虑通过以下方式计算
- 可以设置固定值(width==100,height==300)
- 可以相对于UIScrollView以外的其他控件来计算尺寸
- 2、UIScrollView的frame应该通过`子控件以外的其他控件来计算
- 3、UIScrollView的contentSize通过子控件来计算
- 根据子控件的尺寸以及子控件与UIScrollView之间的间距
19、窗口悬停
不使用自动布局,使用frame
添加几个子控件(UIScrollView ->UIImageView,UIView),直接设置frame确定尺寸
1、分析
- 这个UIView在达到窗口顶部时一直显示在窗口顶部,但是UIScrollView可以继续向上滚动
- 监视UIScrollView的偏移量,当view达到顶部时,将view从UIScrollView中移除,添加到self.view,向下滑动时,到这个原来view的位置时再把view添加到UIScrollView,再向下拖动就方法图片
- 实现时要用一个属性来记录view 在UIScrollView中得位置
- 注意,这里通过storyboard添加的子控件,没有使用自动布局,所以要把自动布局完毕关闭,不然会出现莫名其妙的问题
- 2、实现
- 主要是在滚动scrollView时进行判断
- (void)viewDidLoad { |
自动布局实现
- 自动布局实现貌似又复杂了,使用自动布局的话,不能直接修改frame,否则会出问题,所以这里新建一个大小一致的view,显示到self.view,
— 首先要重新生成一个UIView,最好就是克隆一个和redView一样的view,然后设置在原始位置,滚动到顶部时显示,向下滚动时隐藏。 - 代码如下:
- (void)viewDidLoad { |
20、const和指针以及数组
- 指针与const
void pointAndConst() |
总结:const右边修饰的是神马,那这个神马就不可变(p,*p)
指针和数组
一维数组分析
/* |
总结
1、指针p的加减法运算
- 指针p + N
- p里面存储的地址值 + N * 指针所指向类型的占用字节数
- 指针p - N
- p里面存储的地址值 - N * 指针所指向类型的占用字节数
- 指针p + N
- 2、数组名
- 存储的是数组首元素的地址
- 等价于:一个指向数组首元素的指针
- 数组名 + 1 的跨度:数组首元素的占用字节数
- 3、其他结论
- &num + 1的跨度:num的占用字节数