简历
单例:一个类中只能有一个实例,且为这个实例提供一个访问他的全局节点
优点:能够防止在其他类中,创建出单例的副本,保证单例的唯一性, 能够降低类与类之间的耦合性
代理:为其他对象提供一种代理,以控制对这个对象的访问。
优点:我们给一个对象提供代理,是为了实现这个对象实现不了的方法
观察者:观察者模式是建立对象间一对多的依赖关系,多个观察者对象同时监听一个主题对象。当这个主题对象发生改变时。会通知观察者,他们会自动更新自己
模板方法:我们把不变的行为搬到超类,将可变的部分放入子类。
优点:帮助子类摆脱重复不变行为的纠缠,大大减少了 代码的书写量
策略:定义一系列算法,并将算法封装起来。是他们可以相互替换
优点:策略模式让算法独立于使用它的客户而独立变化
工厂方法:
1.简单工厂模式:我们定义的工厂根据传过来的参数,生产出对应的产品。
优点:简单工厂模式含有必要的逻辑判断,客户不需要考虑生产产品的逻辑,只要提供他们的需求。就能直接生产出参品。去除了具体产品的依赖
缺点:简单工厂模式违背开放封闭原则,使我们想要扩展十分困难。
2.工厂方法模式:
优点:工厂方法模式继承了简单工厂模式封装对象创建过程的优点,有解决了简单工厂模式开放封闭原则的缺点
缺点:每增加一个产品就必须增加一个产品工厂的类,增加了额外的代码量。
Block块:
声明Block作为变量
作为变量使用:
int multiplier = 7 ;
int (^myBlock)( int ) = ^( int num)
{
return num * multiplier;
};
printf ( "%d" , myBlock(3));
__block 变量(block只能在同一个作用域,没法修改块外的任何变量,如果要修改,这要在变量前面加__block)
__block int multiplier = 7 ;
int (^myBlock)( int ) = ^( int num)
{
if (num > 5 )
{
multiplier = 7 ;
}
else
{
multiplier = 10 ;
}
return num * multiplier;
};
Block对于变量都会形成强引用,对self也会形成强引用,从而造成引用循环。为防止这种情况发生,加__weak
XML解析GDataXML框架
一个常见的XML文档一般由以下部分组成
文档声明
元素(Element)
属性(Attribute)
规范的XML文档最多只有一个根元素,其他元素都是根元素的子孙元素。
DOM解析
得到URL,请求得到XML串。将XML转化成数据类型,创建GDataXMLDocument对象(用于解析xml数据的对象),通过
//把取出来的内容放到数组中
NSArray *arr = [documentContent nodesForXPath:@"//User"
error:nil];函数将内容放到数组中,使用发射机制加KVC将数据转换成对象
SAX解析
得到数据
// 1. 实例化一个xml的解析器--通过代理来实现xml的解析
NSXMLParser *parse = [[NSXMLParser alloc] initWithData:data];
// 2. 设置代理
parse.delegate = self;
// 3. 解析器开始解析
[parse parse];
代理五大步骤:
1.打开文档
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
//初始化数组容器,清空容器,便于多次加载数据
[self.videos removeAllObjects];
}
//2.开始节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
//3. 发现节点里面内容
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
// 开始拼接
[self.elementString appendString:string];
}
/4. 结束节点
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
//5 结束文档
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"5 结束文档");
// xml真正解析结束, 可以更新UI, 在主线程
dispatch_async(dispatch_get_main_queue(), ^{
self.dataList = self.videos;
});
}
KVC键值编码
setValue ForKeyPath
ValueForKey
KVO键值监听
// 使用KVO为child添加一个观察者 用于监听happyVal是否被修改了
[child addObserver:self forKeyPath:@"happyVal" options:NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld context:@"监听孩子的欢乐值"];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
然后定义一个父控制器,里面不支持设备旋转。支持竖屏显示
// 支持设备自动旋转
- (BOOL)shouldAutorotate
{
return NO;
}
// 支持竖屏显示
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
我们剩下的控制器都继承与这个控制器,若不支持旋转什么也不用做。若支持旋转,将函数
- (BOOL)shouldAutorotate
{
return NO;
}返回YES
然后得到屏幕的长度和宽度。
iOS自带感应函数,将屏幕横放会调用的函数
(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
将长和宽对调
删除页面,从新加载新页面。屏幕旋转成功
GCD(伟大的中央调度器)
他是IOS4后才引进的一种多线程技术。开发者只需要定义想执行的任务加到队列中,GCD就能生成必要的线程技术,其实质就是队列
优点:
1.GCD解决线程多核并行运算问题
2.GCD自动管理生命周期
3.GCD无需线程,只需将任务放到队列中
遵循规则:先进先出
(主线程里面不能同步获取主队列, 会造成相互引用造成死锁)
同步串行
同步并行
异步串行
异步并行
主队列
全局队列
(更新UI必须在主线程进行,否则会造成界面卡顿延时)
运行循环:每个线程都有一个运行循环,但是只有主线程的运行循环在程序运行时刻开启,子线程默认关闭。我们一般不要在子线程中设置代理,和计时器。
开启
do{
// [[NSRunLoop currentRunLoop] run];
// 让运行循环每隔0.1秒运行一下
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}while(!self.finished);
NSOperation
NSOperation其实是对GCD进一步封装,但是他并没有封装GCD中所有的方法,相当于全局队列。
SQLite
iOS的数据库的存储方式:
1.数据库
2.preference(偏好设置)
3.Plist(NSArray\NSDictionary):Plist文件只能存放基本对象类型即数组和字典。
4.NSCoding(NSKeyedArchiver\NSKeyedUnarchiver)
除了数据库外,里面的三种存储方式,有致命的缺点,就是不能够放大内存。(原因:我们每当使用以上三种存储方式,我们使用存储数据时都会将存入的所有数据都取出来放到内存中,在中间找到想要的数据,这样如导致手机内存消耗较大而卡死退出程序)
SQLite:数据库,纯C语言。轻量级。大批量数据缓存首选SQLite。
Core Data:数据库,基于SQLite3,OC版本,庞大,重量级。
SQLite:
优点:SQLite是一款轻型的嵌入式数据库,他占用资源非常低,在嵌入式设备中,可能只需要几百K的内存就足够了。而且他的处理处理速度比MySQL 和 PostGreSQL还快
数据库定义:数据库(database)是按照数据结构来组织、存储和管理数据的仓库
分为两大类:关系型数据库(主流) 对象性数据库
常用关系型数据库
PC端:Oracle、MySQL、SQL Server、Access、DB2、Sybase
嵌入式\移动客户端:SQLite
数据库是如何存储数据的
数据库的存储结构和excel很像,以表(table)为单位
数据库存储数据的步骤
新建一张表(table)
添加多个字段(column,列,属性)【数据库中不可以使用关键字来命名表、字段】
添加多行记录(row,record,每行存放多个字段对应的值)
什么是SQL
SQL(structured query language):结构化查询语言
SQL是一种对关系型数据库中的数据进行定义和操作的语言
SQL语言简洁,语法简单,好学好用
什么是SQL语句
使用SQL语言编写出来的句子\代码,就是SQL语句
在程序运行过程中,要想操作(增删改查,CRUD)数据库中的数据,必须使用SQL语句
SQL语句的特点
不区分大小写(比如数据库认为user和UsEr是一样的)
每条语句都必须以分号 ; 结尾
数据库中不可以使用关键字来命名表、字段
SQL语句操作:
创建表
create table if not exists 表名 (字段名1 字段类型1,字段名2 字段类型2,…..)
字段类型:
SQLite将数据划分为以下几种存储类型:
integer : 整型值
real : 浮点值
text : 文本字符串
blob : 二进制数据(比如文件)
实际上SQLite是无类型的
就算声明为integer类型,还是能存储字符串文本(主键除外)
建表时声明啥类型或者不声明类型都可以,也就意味着创表语句可以这么写:
create table t_student(name, age);
为了保持良好的编程规范、方便程序员之间的交流,编写建表语句的时候最好加上每个字段的具体类型
create table t_student (id integer, name text , age inetger, score real) ;
删除表
drop table if exists t_student;
插入数据
insert into t_student(name, age) values(‘mm’, 10);
注意:
数据库中的字符串内容应该用单引号括住,不可用双`引号
更新数据:
update t_student set name = ‘jack’ , age = 20 where name = ‘xiaming’ and age < 10
查询:
select * from t_student where age > 10
示例
select name myname, age myage from t_student ;
给name起个叫做myname的别名,给age起个叫做myage的别名
select s.name, s.age from t_student s ;
给t_student表起个别名叫做s,利用s来引用表中的字段示例
select count (age) from t_student ;
select count ( * ) from t_student where score >= 60;
排序:
查询出来的结果可以用order by进行排序
select * from t_student order by 字段 ;
select * from t_student order by age ;
默认是按照升序排序(由小到大),也可以变为降序(由大到小)
select * from t_student order by age desc ; //降序
select * from t_student order by age asc ; // 升序(默认)
也可以用多个字段进行排序
select * from t_student order by age asc, height desc ;
先按照年龄排序(升序),年龄相等就按照身高排序(降序)
limit 分页查询:
使用limit可以精确地控制查询结果的数量,比如每次只查询10条数据
格式
select * from 表名 limit 数值1, 数值2 ;
示例
select * from t_student limit 4, 8 ;
可以理解为:跳过最前面4条语句,然后取8条记录
limit常用来做分页查询,比如每页固定显示5条数据,那么应该这样取数据
第1页:limit 0, 5
第2页:limit 5, 5
第3页:limit 10, 5
…
第n页:limit 5*(n-1), 5
猜猜下面语句的作用
select * from t_student limit 7 ;
相当于select * from t_student limit 0, 7 ;
表示取最前面的7条记录
简单约束:
建表时可以给特定的字段设置一些约束条件,常见的约束有
not null :规定字段的值不能为null
unique :规定字段的值必须唯一
default :指定字段的默认值
(建议:尽量给字段设定严格的约束,以保证数据的规范性)
示例
create table t_student (id integer, name text not null unique, age integer not null default 1) ;
name字段不能为null,并且唯一
age字段不能为null,并且默认为1
主键约束:
如果t_student表中就name和age两个字段,而且有些记录的name和age字段的值都一样时,那么就没法区分这些数据,造成数据库的记录不唯一,这样就不方便管理数据
良好的数据库编程规范应该要保证每条记录的唯一性,为此,增加了主键约束
也就是说,每张表都必须有一个主键,用来标识记录的唯一性
什么是主键
主键(Primary Key,简称PK)用来唯一地标识某一条记录
例如t_student可以增加一个id字段作为主键,相当于人的身份证
主键可以是一个字段或多个字段
主键的设计原则:
主键应当是对用户没有意义的
永远也不要更新主键
主键不应包含动态变化的数据
主键应当由计算机自动生成
主键的声明:
在创表的时候用primary key声明一个主键
create table t_student (id integer primary key, name text, age integer) ;
integer类型的id作为t_student表的主键
主键字段
只要声明为primary key,就说明是一个主键字段
主键字段默认就包含了not null 和 unique 两个约束
如果想要让主键自动增长(必须是integer类型),应该增加autoincrement
create table t_student (id integer primary key autoincrement, name text, age integer) ;
外键约束:
利用外键约束可以用来建立表与表之间的联系
外键的一般情况是:一张表的某个字段,引用着另一张表的主键字段
新建一个外键
create table t_student (id integer primary key autoincrement, name text, age integer, class_id integer, constraint fk_student_class foreign key (class_id) references t_class (id));
t_student表中有一个叫做fk_t_student_class_id_t_class_id的外键
这个外键的作用是用t_student表中的class_id字段引用t_class表的id字段
表连接查询:
什么是表连接查询
需要联合多张表才能查到想要的数据
表连接的类型
内连接:inner join 或者 join (显示的是左右表都有完整字段值的记录)
左外连接:left outer join (保证左表数据的完整性)
示例
查询0316iOS班的所有学生
select s.name,s.age from t_student s, t_class c where s.class_id = c.id and c.name = ‘0316iOS’;
FMDB框架的使用:
什么是FMDB
FMDB是iOS平台的SQLite数据库框架
FMDB以OC的方式封装了SQLite的C语言API
FMDB的优点
使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
对比苹果自带的Core Data框架,更加轻量级和灵活
提供了多线程安全的数据库操作方法,有效地防止数据混乱
FMDB的github地址
https://github.com/ccgus/fmdb
FMDB有三个主要的类
FMDatabase
一个FMDatabase对象就代表一个单独的SQLite数据库
用来执行SQL语句
FMResultSet
使用FMDatabase执行查询后的结果集
FMDatabaseQueue
用于在多线程中执行多个查询或更新,它是线程安全的。
打开数据库:
通过指定SQLite数据库文件路径来创建FMDatabase对象
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@"数据库打开失败!");
}
文件路径有三种情况
具体文件路径:如果不存在会自动创建
空字符串@“”:会在临时目录创建一个空的数据库,当FMDatabase连接关闭时,数据库文件也被删除
nil:会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁
执行更新:
在FMDB中,除查询以外的所有操作,都称为“更新”
create、drop、insert、update、delete等
使用executeUpdate:方法执行更新
- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
示例
[db executeUpdate:@"UPDATE t_student SET age = ? WHERE name = ?;", @20, @"Jack"]
执行查询:
查询方法
- (FMResultSet *)executeQuery:(NSString*)sql, ...
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
示例
// 查询数据
FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_student"];
// 遍历结果集
while ([rs next]) {
NSString *name = [rs stringForColumn:@"name"];
int age = [rs intForColumn:@"age"];
double score = [rs doubleForColumn:@"score"];
}
FMDatabaseQueue:
FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题
为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类
FMDatabaseQueue的创建
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
简单使用
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
FMResultSet *rs = [db executeQuery:@"select * from t_student"];
while ([rs next]) {
// …
}
}];
使用事务:
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
FMResultSet *rs = [db executeQuery:@"select * from t_student"];
while ([rs next]) {
// …
}
}];
事务回滚
*rollback = YES;
因为IOS中的数据库API在使用上非常复杂繁琐,我们在对SQLite数据库进行操作时通常使用第三方封装的库FMDB
FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。
FMDB常用类:
FMDatabase:一个单一的SQLite数据库,用于执行SQL语句。
FMResultSet:执行一个FMDatabase结果集。
FMDatabaseQueue:在多个线程中执行查询和更新时会用到这个类。
使用FMDB需要导入地层库 libsqlite3.0.dylib依赖包导入,
1、当给定路径的数据库文件不存在时,FMDB会自动创建一个
2、如果传入的数据库路径是一个空串:即@"", 则FMDB会在临时文件目录下创建这个数据库,数据库断开连接时,数据库文件会被删除。
3、如果数据库路径是NULL,则它会建立一个在内存中的数据库,当数据库断开连接时,数据库文件会被删除。
知识点二:数据库的打开和关闭以及表格的创建。
知识点三:表格数据的增删改查。
知识点四:多线程操作数据库。
二次封装FMDB
封装FMDB使得我们更好的创建数据库,能更加容易使用数据库并使用他的增删改查等功能
1.首先我们创建一个单例。并在单例中创建一个数据库。
创建表:
2.封装创建表格的方法,我们传过来一个表名,在封装函数里面拼接SQLite语句。使用[fmdb executeUpdate:sqlString];创建出一个数据库。
插入输数据到数据库:
3.创建插入操作。传入表名和对象属性的集合(BOOL类型)
(1)判断数据库表是否存在,如果存在继续,若不存在则调用单例创建出数据库
(2)使用反射机制,通过表名得到对象属性的个数。
(3)遍历对象属性,通过KVC得到属性值,判断属性值是否存在,如果存在就放到字典中
(4)封装一个将字典插入数据库方法(BOOL类型)
(5)传入表名,设置一个可变字符串,用于拼接SQLite语句中的插入数据库语句,使用NSArray *array = [dic allKeys];方法得到所有的键,循环中先放入键值在加上“,”,循环完后会有多余的“,”号。我们
[sqlString deleteCharactersInRange:NSMakeRange([sqlString length] - 1, 1)]; 在中间加入“)VALUES (”后再次使用循环来拼接“?,”。循环完成后再次删除最后一位小数点,再拼接右括号。
if ([fmdb executeUpdate:sqlString withArgumentsInArray:[dic allValues]])
{
return YES;
}
(6)得到返回值,插入函数返回得到的返回值,若返回为YES则插入成功。否者插入失败
删除:(无返回值)传入表明 和可变字典【删除一条记录】
声明一个可变字符串,拼接SQL语句(删除语句)
[sqlString appendString:[NSString stringWithFormat:@"DELETE FROM %@ WHERE %@ LIKE ?", tableName, [[keyDic allKeys] objectAtIndex:0]]];
使用函数从字典的到键值的数组,并得到数组的个数
当数组大于1时,我们使用for循环拼接
NSString *strKey = [[keyDic allKeys] objectAtIndex:i];
[sqlString appendString:[NSString stringWithFormat:@" AND %@ LIKE ?", strKey]];
拼接完成荷后调用FMDB框架函数
[fmdb executeUpdate:sqlString withArgumentsInArray:[keyDic allValues]];
【删除所有记录】
-(void)wzDeleteReCordFromTableName:(NSString *)tableName
{
NSString *sqlString = [NSString stringWithFormat:@"DELETE FROM %@", tableName];
[fmdb executeUpdate:sqlString];
}
//修改记录
- (void)wzModifyRecorderData:(NSString *)tableName andNewDictionary:(NSMutableDictionary *)dic andOriginDictionary:(NSMutableDictionary *)keyDic;
{
NSMutableString *sqlString = [NSMutableString string];
[sqlString appendString:[NSString stringWithFormat:@"UPDATE %@ SET ",tableName]];
NSInteger m = [[dic allKeys] count];
for (int i = 0; i < m; i++)
{
[sqlString appendString:[[dic allKeys] objectAtIndex:i]];
[sqlString appendString:@" = ?, "];
}
[sqlString deleteCharactersInRange:NSMakeRange([sqlString length] - 2, 2)];
[sqlString appendString:@" WHERE "];
NSInteger j = [[keyDic allKeys] count];
for (int i = 0; i < j; i++)
{
[sqlString appendString:[[keyDic allKeys] objectAtIndex:i]];
[sqlString appendString:@" LIKE ? "];
[sqlString appendString:@"AND "];
}
[sqlString deleteCharactersInRange:NSMakeRange([sqlString length] - 4, 4)];
NSMutableArray *mutableArr = [[NSMutableArray alloc] initWithCapacity:1];
for (NSString *str in [dic allValues])
{
[mutableArr addObject:str];
}
for (NSString *str in [keyDic allValues])
{
[mutableArr addObject:str];
}
[fmdb executeUpdate:sqlString withArgumentsInArray:mutableArr];
}
查询:(查询某一条或几条记录,查询所有记录)【得到返回值是数组】
[1]范围查询:【传递数据库表名,以及两个字符串类型的属性(用于查询两个数据库之间的范围)】
思路:依然是拼接SQlite语句然后使用FMDB框架中的FMResultSet的对象调用 dataBase.fmrs = [fmdb executeQuery:sqlString withArgumentsInArray:[keyDic allValues]];
while ([fmrs next])
{
id user = [AssignToObject reflectDataFromOtherObject:fmrs
andObjectStr:tableName];
[returnArray addObject:user];
}
return returnArray;
//调用函数
//用字典为类的各个属性赋值
+ (id)reflectDataFromOtherObject:(FMResultSet *)dataSource andObjectStr:(NSString *)classStr
{
id model = [[NSClassFromString(classStr) alloc] init];
for (NSString *key in [self propertyKeysWithString:classStr])
{
id propertyValue = [dataSource stringForColumn:key];
//该值不为NSNULL,并且也不为nil
if (![propertyValue isKindOfClass:[NSNull class]] && propertyValue != nil)
{
//为对象的各个属性赋值
[model setValue:propertyValue forKey:key];
}
}
return model;
}
得到数据库表名(我们在之前创建数据库,数据库表名和属性类名一致)
思路:拼接查询数据库SQLite,得到查询对象FMResultSet类型
使用循环,当FMResultSet不为0时,调用函数
[1]通过反射机制的到对象属性的对象,和属性(即键值)和键值的个数.从而得到键值数组
遍历键值数组,使用 id propertyValue = [dataSource stringForColumn:key];方法,得到具体的属性数据,判断一下属性数据是否为NULL,若不为空,则使用KVC将属性数据和属性以键值对放入对象之中。返回对象。这样我们就能查询到数据库中某一表中所有的数据
[2]
即时通讯:
【1】首先制作推送证书
【2】将证书传给后台,得到APPKey【注册环信开发者账号获得APPKey】(应用授权)
【3】然后我们从后台中请求到自己在环信登陆的张号和密码
【4】将密码和账号登陆到环信
【5】形成关联
上下拉刷新:PullingRefreshTableView
【1】创建刷新表格对象,使用其代理
//开始刷新
[_PtabelView launchRefreshing];
解决bug:
【1】返回使必须将
KVC:键 值编码
【1】对对象的基本属性进行赋值,setValue: forKey:
【2】对对象的成员属性进行赋值,setValue: forKeyPath:
【3】对对象的所有属性进行赋值,setValuesWithDictionary:
【4】通过键值取出对象属性: ValueForKeyPath:
KVO 键值监听
【1】一般用于对成员的某个属性值进行监控。
addObserver:self forKeyPath:、
内存优化LRU是Least Recently Used 近期最少使用算法。
内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。
内存优化
使用NSCache做内存缓存(NSCache是苹果官方提供的缓存类,用法与NSMutableDictionary的用法很相似)
我们为了确保接收到内存警告时,能够真正释放内存,最好调用removeAllObjects
NScache是线程安全的,在多线程操作中,不需要对Cache加锁。
totalCostLimit :缓存空间的最大成本,超出上限会自动回收对象。默认值是0没有限制。
totalCostLimit是展现设置内存的大小
countLimit:能够缓存对象的最大数量,默认值也是0(默认没有限制)
【当对象数量或者是内存大于设定,我们会自动删除最开始放入的对象或者将最开始的对象开始删除直到使用内存小于规定内存】
有沙盒缓存:可使用SDWebImage可以直接缓存到沙河。
数据库缓存:使用FMDB框架将数据缓存到SQLite数据库
使用Core Data框架通过ORM机制,将对象映射到数据库【底层实现:基于SQLite3数据库】
装逼阶段:CoreData;
1.创建步骤:
【1】创建实体模板,在模板内创建有关的实体
【2】由模板内的实体生成对应的实体类
【3】创建一个NSManagedObjectModel类,由此类对象从实体模板读取数据
【4】创建一个持久化存储助理类NSPersistentStoreCoordinator同时传入NSManagedObjectModel类对象。
【5】创建数据库路径(获取沙盒Document路径, 拼接数据库路径)
【6】持久化存储助理类添加路径
【7】创建上下文,NSMangerObjectContext,并设置他的.coordinator等于持久化存储助理类
与FMDB相比较
优点:【1】不用操纵SQL语句。就能够实现数据的存储,【2】不用谢Model模型类,能够由实体模板自动生成 【3】能处理复杂的对象类型,能够一次性实现整体存储 【4】我们不需要表与表之间的关系
牛鼻技术
【1】图片轮播
思路:
1.创建出一个scrollView对象,将图片加到scroller对象上面,扩展它的宽度,并遵循代理方法
2.设置页面指示器【设置页面指示器的中心点, 其他页面指示器的颜色, 当前页面指示器的颜色,设置分页器的个数, 设置默认在那一页(一般默认为第一页0)】
3.设置计时器 (获取当前消息的循环,利用消息循环设置计时器的对象的优先级和控件的优先级和控制器的优先级相同)
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSRunLoopCommonModes];
考虑:
开始滑动
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
1.如果我们用手拖拽,我们就需要将计时器关掉[self.timer invalidate];并将计时器赋值为一个空指针。
滑动过程
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
2.在拖拽过程中,我们使用
// 先获根据内容的偏移位置,获取当前的页数
int page =( scrollView.contentOffset.x+scrollView.frame.size.width*0.5)/ scrollView.frame.size.width;获取到当前页数
将当前页码告知分页控制器,是分页控制器找到位置self.play.currentPage = page;
滑动结束
3.在滑动结束后,我们建一个计时器(消除BUG),获取当前运行循环,将计时器优先级和控件优先级相同
没有滑动,使用计时器
首先获取当前页数,NSInteger page = self.play.currentPage;
图片轮播需要一直循环,故我们判断当前页数是否为最后一页(及总页数和-1),我们将Page重新置为0,否者的话将页数+1,
使用动画方式轮播[setcontentOffset]
[self.scroll setContentOffset:CGPointMake(page*self.scroll.frame.size.width, 0) animated:YES];
【2】使用近身传感远程设置滚动图片(注:只要是在接受通知自动更新自己的方法里面写什么方法,就会执行什么方法)
接受传感器的观察者对象的方法。
[[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeImage:) name:@"UIDeviceProximityStateDidChangeNotification" object:nil];
协议总结
http协议:HTTP是一个属于应用层的面向对象的协议
http请求由三部分组成,分别是:请求行、消息报头、请求正文
特点:
【1】适用性好(支持客户或服务器模式)
【2】简单快速。我们只需传送请求方法和路径
【3】灵活性高,可以传输任意类型的数据对象,正在传输的类型由Content-Type加以标记。
【4】无连接:每次只能处理一个请求
【5】无状态:http协议是无状态协议,没有记忆功能
GET 请求获取Request-URI所标识的资源
POST 在Request-URI所标识的资源后附加新的数据
HEAD请求获取由Request-URI所标识的资源的响应消息报头
PUT请求服务器存储一个资源,并用Request-URI作为其标识
DELETE请求服务器删除Request-URI所标识的资源
TRACE请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT 保留将来使用
OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求