iOS笔记056 - UI总结02
九宫格布局
UICollectionViewController
创建控制器一定要指定默认的布局样式。
// 加载一个九宫格布局的控制器,必须指定布局样式
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
vc = [[SLQGuideCollectionController alloc] initWithCollectionViewLayout:layout];
也可以重写控制器的init方法
- (instancetype)init
{
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
// 初始化必须指定默认的布局样式
return [super initWithCollectionViewLayout:layout];
}
在指定布局时可以设置各种属性
- (instancetype)init
{
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
// cell大小
layout.itemSize = SLQScreenBounds.size;
// 水平间距
// layout.minimumInteritemSpacing = 0;
// 垂直间距
layout.minimumLineSpacing = 0;
// 每一组距离四面的距离
// layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
// 滚动方向
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 初始化必须指定默认的布局样式
return [super initWithCollectionViewLayout:layout];
}
如果想显示控件,那么使用方法和UITableView非常相似。使用代理设置每个CollectionView
// 一共多少组
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
// 某组多少元素
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 4;
}
// cell 的内容
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 只能以这种方式创建cell,首先注册xib或者类,然后去缓存池中取,如果缓存池没有就自己创建一个新的cell
SLQGuideCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:IDforIndexPath:indexPath];
// 设置cell内容
NSString *imageName = [NSString stringWithFormat:@"guide%ldBackground",indexPath.item + 1];
cell.image = [UIImage imageNamed:imageName];
return cell;
}
运行时 - runtime
首先包含头文件,然后使用里面的方法即可
// 运行时对象
#import <objc/runtime.h>
// 遍历某个类里面所有属性 Ivar:表示成员属性
// copyIvarList只能获取哪个类下面的属性,并不会越界(不会把它的父类的属性给遍历出来)
// Class 获取哪个类的成员属性
// count:告诉你当前类里面成员属性的总数
// unsigned int count = 0;
// // 返回成员属性的数组
//
int count = 0;
Ivar *name = class_copyIvarList([UIGestureRecognizer class], &count);
for (int i = 0; i < count; i ++) {
Ivar ivar = name[i];
// 获取属性名
NSString *proName = @(ivar_getName(ivar));
NSLog(@"%@",proName);
}
//<UIScreenEdgePanGestureRecognizer: 0x7fb6ba46f1c0; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7fb6ba7481b0>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fb6ba46d8e0>)>>
//UIScreenEdgePanGestureRecognizer:手势类型
//target - _UINavigationInteractiveTransition
//action - handleNavigationTransition
可以看到系统默认在滑动手势时作的一些事情,指定了手势的target和action,可以利用这些方法来自定义自己的手势。
自定义系统默认生成的手势
1、首先要找到这个手势相关联的属性和方法。因为是私有的,不能直接看到,所以只能通过运行时机制获取属性名
先通过运行时机制的一些函数,观察属性名,然后确定在自己要得。
int count = 0;
Ivar *name = class_copyIvarList([UIGestureRecognizer class], &count);
for (int i = 0; i < count; i ++) {
Ivar ivar = name[i];
// 获取属性名
NSString *proName = @(ivar_getName(ivar));
NSLog(@"%@",proName);
}
2、找出属性名并添加手势
// 找到属性名
NSArray *arr = [self.interactivePopGestureRecognizer valueForKey:@“_targets"];
// 获取属性
id objc = [arr firstObject]; // -(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f7f93f5adf0>)
// 获取方法target
id target = [objc valueForKey:@"_target"]; //
// 添加自定义手势,指定方法位系统内部私有的方法handleNavigationTransition:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
pan.delegate = self;
[self.view addGestureRecognizer:pan];
3、实现代理方法-只要不是根控制器就使用手势
// UIGestureRecognizerDelegate 代理方法
// 是否开始手势,如果是不是根控制器就开始手势
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 判断下当前控制器是否是跟控制器
return (self.topViewController != [self.viewControllersfirstObject]);
}
高斯模糊实现
这个方法是别人封装好的,直接拿来使用即可。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 2 && indexPath.row == 0) {
// 弹出窗口,指定frame
SLQSettingBlurView *blur = [[SLQSettingBlurView alloc] initWithFrame:SLQScreenBounds];
[SLQKeyWindow addSubview:blur];
// 弹出提示窗口
[MBProgressHUD showSuccess:@"没有最新版本"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 隐藏高斯窗口
[blur removeFromSuperview];
});
}
}
block 循环利用
// block会把代码里所有强指针全部强引用
// 解决循环利用的问题
// __weak XMGScoreViewController *weakSelf = self;
// typeof获取括号里面的类型
__weak typeof(self) weakSelf = self;
// 在iOS7之后只要在cell上添加textField都自动做了键盘处理
item.itemUpdate = ^(NSIndexPath *indexPath)
{
// 获取当前选中的cell
UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:indexPath];
// 弹出键盘
UITextField *textField = [[UITextField alloc] init];
[textField becomeFirstResponder];
[cell addSubview:textField];
};
json文件
文件中保存的时字典数据
[
{
"title" : "如何领奖?",
"html" : "help.html",
"id" : "howtoprize"
},
{
"title" : "如何充值?",
"html" : "help.html",
"id" : "howtorecharge"
},
]
直接当做普通文件读取就行
- (NSMutableArray *)items
{
if (_items == nil) {
_items = [NSMutableArray array];
NSString *fullPath = [[NSBundle mainBundle] pathForResource:@"help.json" ofType:nil];
NSData *data = [NSData dataWithContentsOfFile:fullPath];
// 从文件读取数据
NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
for (NSDictionary *dict in allData) {
SLQHtmlItem *item = [SLQHtmlItem itemWithDict:dict];
[_items addObject:item];
}
// NSLog(@"%@",allData);
}
// NSLog(@"%@",_items);
return _items;
}
关键一句话是使用 NSJSONSerialization 对文件进行解析
NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
文件中读取的关键字和系统保留字有冲突
那么读取时就要进行修正,使用KVC进行字典读取要保证,模型中得属性和字典中元素数量和名称一致,不能有任何差别。
现在的问题就是,文件中又一项数据的key是id,这个和系统的保留字id冲突,必须对id进行转换。所以声明属性是大写ID。
@property (strong, nonatomic) NSString *ID;
然后是初始化方法,使用 KVC进行读取
+ (instancetype)itemWithDict:(NSDictionary *)dict
{
SLQHtmlItem *item = [[self alloc] init];
// KVC,会出问题,id 和 ID无法自动转换
[item setValuesForKeysWithDictionary:dict];
// 使用通用方法更加方便,抽出分类
// SLQHtmlItem *item = [SLQHtmlItem objectWithDict:dict mapDict:@{@"ID":@"id"}];
return item;
}
重写setvalue方法,在方法里进行转换,这个可以应对数量较少的键值对冲突,如果有十几个或者更多,使用起来就很麻烦,要写一堆if语句。
// 因json文件中得字典key 是id,与系统关键字冲突,手动判断再返回正确的值
- (void)setValue:(id)value forKey:(NSString *)key
{
// 判断是不是id
if ( [key isEqualToString:@"id"]) {
[self setValue:value forKey:@"ID"];
}
else
{
[super setValue:value forKey:key];
}
}
更加方便的方法是抽出一个 分类,因对更加复杂的情况,如果有10个key和系统关键字重复,这个分类比较好使。
// 快速进行字典转模型
// mapDict:模型中的哪个属性名跟字典里面的key对应
+ (instancetype)objectWithDict:(NSDictionary *)dict mapDict:(NSDictionary *)mapDict
{
id obj = [[self alloc] init];
// 运行时遍历模型中得属性
unsigned int count = 0;
Ivar *ivar = class_copyIvarList(self, &count);
for (int i = 0 ; i < count ; i ++) {
// 取出
Ivar var = ivar[i];
// 取出模型
NSString *name = @(ivar_getName(var));
// s输入如下,有一个_,直接去掉就可得到属性名
// 菜皮[61496:622121] _title
// 菜皮[61496:622121] _html
// 菜皮[61496:622121] _ID
// 去除下划线
name = [name substringFromIndex:1];
id value = dict[name];
// 需要由外界通知内部,模型中属性名对应字典里面的哪个key
// ID -> id
if (value == nil) {
//
if(mapDict)
{
// 获取真实的key
NSString *key = mapDict[name];
value = dict[key];
}
}
[obj setValue:value forKey:name];
// NSLog(@"%@",name);
}
return obj;
}
使用方法,要初入一个冲突的字典
SLQHtmlItem *item = [SLQHtmlItem objectWithDict:dict mapDict:@{@"ID":@"id"}];
iOS笔记056 - UI总结02的更多相关文章
- iOS笔记057 - UI总结03
控制器的父子关系 1.控制器父子关系的建立原则 如果2个控制器的view是父子关系(不管是直接还是间接的父子关系),那么这2个控制器也应该为父子关系 [self.view addSubv ...
- iOS笔记055 - UI总结01
1.程序启动后的开始动画 程序启动后可以加载一个简单的动画界面来介绍程序或者用户信息. 可以使用一个xib来描述界面.并且如果想在程序加载完成后第一个加载这个xib文件,需要在Appdelegat ...
- iOS开发Swift篇(02) NSThread线程相关简单说明
iOS开发Swift篇(02) NSThread线程相关简单说明 一 说明 1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明. 2)该文仅仅简单讲解NSThread在s ...
- 李洪强iOS开发之-环信02.1_环信 SDK 2.x到3.0升级文档
李洪强iOS开发之-环信02.1_环信 SDK 2.x到3.0升级文档 SDK 2.x 至 3.0 升级指南 环信 SDK 3.0 升级文档 3.0 中的核心类为 EMClient 类,通过 EMCl ...
- 荼菜的iOS笔记--UIView的几个Block动画
前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...
- 免费素材下载:iOS 8 矢量 UI 素材套件
小伙伴们,苹果终于在今天凌晨推送了 iOS 8 的正式版.虽然该系统并未与 iPhone6 发布会同时亮相,但对于已经提前体验尝鲜过测试版的同学来说并不陌生.iOS 8 几乎每个图标都进行了重新设计, ...
- iOS之微博UI实例--拟物化设计(成功了90%)
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 李洪强iOS开发之-环信02.2_环信官网下载环信 SDK
李洪强iOS开发之-环信02.2_环信官网下载环信 SDK 移动客服即时通讯云 iOS SDK 当前版本:V3.1.4 2016-07-08 [ 版本历史 ] | 开发指南 | 知识库 | Demo源 ...
- IOS开发-UI学习-sqlite数据库的操作
IOS开发-UI学习-sqlite数据库的操作 sqlite是一个轻量级的数据库,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了,而且它的处理速度比Mysql.PostgreSQL这 ...
随机推荐
- python 爬poj.org的题目
主要是正则表达式不熟练,基础知识不扎实,函数也不怎么会用,下次再深入了解这3个函数吧. 主要是一个翻页的功能,其实,就是通过一个url替换一下数字,然后得到一个新的url,再找这个新的链接的信息. # ...
- 字符串处理(POJ1782)
题目链接:http://poj.org/problem?id=1782 解题报告: #include <iostream> #include <cstdio> #include ...
- BZOJ 3233: [Ahoi2013]找硬币
BZOJ 3233: [Ahoi2013]找硬币 标签(空格分隔): OI-BZOJ OI-DP Time Limit: 10 Sec Memory Limit: 64 MB Description ...
- printf、sprintf与fprintf 的用法区分
原文链接 1: fprintf()#include <stdio.h> int fprintf( FILE *stream, const char *format, ... );fprin ...
- apache单ip配置多端口多站点
1.修改 /etc/httpd/conf/httpd.conf 添加一个Listen,如: Listen 80 Listen 8001 Listen 8002 2.添加一个VirtualHost #v ...
- 旧文备份: CANopen的LSS子协议中文翻译
有关节点地址和网络波特率的在线设置等:下载
- open cv & vs
原来基于vs和msdn一起读视频,结果发现现在的函数不能用了.找不到合适的解码器了,只好转战opencv. 具体怎么用,网上查吧,不过opencv读视频的例子,可以见这个. http://blog.c ...
- C++编程经验总结1
面向对象的精髓: 主函数其实就是对于类的元素和动作的重新组合来进行一项活动. 一个思想概念:程设是清楚的,完美的. 数学是清楚的,是完美的. 物理是有趣的,尤其是量子物理 生物是清楚的,尤其是基因 外 ...
- jquery-ui-custom autocomplete
//jsp <%@ page language="java" import="java.util.*" pageEncoding="utf-8& ...
- BZOJ4008: [HNOI2015]亚瑟王(期望dp)
Time Limit: 20 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 1952 Solved: 1159[Submit][Status] ...