218.241.181.202 wxhl60 123456
192.168.10.253 wxhl66 wxhl66
CSDN论坛
github
cocoachina
code4app
拉勾网
友盟
Boss
shareSDK
CoreImage 内置的滤镜
融云 www.rongcloud.cn
{
目录:
😀、iOS 开发入门
😃、视图与窗口
😀、AVAudioPlayer
😊、多线程
😉、GCD(Grand Central Dispatch) 队列
😍、网络编程
😘、绘图与文本
😚、正则表达式
😗、沙盒路径
😙、CALayer
😜、核心动画
😝、睡眠
😛、UIImagePicker 和 相册
😳、触摸
😁、手势
😔、多媒体
😌、block
😒、添加字体
😞、常用控件
😣、视图控制器
😢、导航控制器
😂、标签控制器
😭、滑动视图
😪、Sqlite数据库
😥、表视图
😰、UICollectionView 集合视图
😅、视图控制器的侧滑 MMDrawController
😓、超文本链接
😩、Foundation框架
😫、GPS和地图
😨、MBProhressHUD 风火轮、活动监视
😱、富文本专辑
😠、引导界面
😡、CoreImage
😤、宏定义那件小事
😖、UIApplication
😆、C语言常用函数
😋、cocoapods安装
😷、发起通电
}
==================================================================================================================================================
》》》OC知识
成员变量,有三种权限,就是大家都知道的@private、@protected、@public ,写在.m文件中时,相当于是@private权限,子类无法访问,验证了一下,做权限修改也无效。而写在.h文件中,默认是@protected权限,子类可以访问,可以做权限修改。
使用@property声明的变量实际上就如在.m文件中声明的变量一样,是真正私有化的,@property声明的变量做了三件事
1.在.ml文件中声明一个@private的变量(不是在.h文件中声明@private变量)
2.声明setter和getter方法
3.定义setter和getter的实现
使用@property声明的变量,子类是不能继承的,分类是不能直接访问的
==================================================================================================================================================
{
iOS初级
😀、iOS 开发入门
一、iOS概述
1.iOS于2007年9月1日发布,和Mac OS X都基于UNIX系统
2.苹果公司每年都会召开开发者大会(WWDC),期间会发布最新iOS系统版本
3.iOS架构四个层次:可触摸层(cocoa touch)、媒体层(media services)、核心服务层(core services)、核心操作系统层(core OS)
4.项目信息 Product Name : 项目名
Organization Name : 公司名
Organization Identifier : 倒置后的网址
Bundle Identifier : 唯一标识符
Language : 开发语言
Dvices : 运行的设备
5.UI(user interface)
6.二倍图片 @2x 三倍图片 @3x png类型的图片可以省略格式
7.APP图标尺寸 60*60
8.修改APP名:Info.plist -> Add Row -> Bundle Display Name
9.尺寸与分辨率 尺寸 宽*高 分辨率
3.5 320*480 640*960
4.0 320*568 640*1136
4.7 375*667 750*1334
5.5 414*736 1242*2208
10、导航栏44px 状态栏20px 标签栏49px
获取设备信息
UIDevice *device = [[UIDevice alloc] init];
NSString *name = device.name; //获取设备所有者的名称
NSString *model = device.name; //获取设备的类别
NSString *type = device.localizedModel; //获取本地化版本
NSString *systemName = device.systemName; //获取当前运行的系统
NSString *systemVersion = device.systemVersion;//获取当前系统的版本
}
==================================================================================================================================================
{
😃、视图与窗口
一、窗口 一方面提供一个区域来显示视图,另一方面将事件分发给视图
//1、获取当前设备屏幕对象
UIScreen *screen = [UIScreen mainScreen];
//2、用对象的位置、大小创建窗口
_window = [[UIWindow alloc] initWithFrame:screen.bounds];
//3、给窗口背景添加颜色
_window.backgroundColor = [UIColor blueColor];
//4、设置窗口的根视图控制器
[_window setRootViewController:[[UIViewController alloc] init]];
//5、显示窗口
[_window makeKeyAndVisible];
//设置优先级
_window.windowLevel = UIWindowLevelAlert; //设置窗口优先级 会把状态栏遮住
二、视图
1、alpha 不透明度,小于0.01的视图不接受点击事件
(重要)2、clipsToBounds 默认是NO,当设置为yes时,超出当前视图的尺寸的内容和子视图不会显示。layer.cornerRadius
3、hidden 是否隐藏,默认是NO
4、userInteractionEnabled 是否开启用户交互,默认是YES(UIImageView默认是NO)
5、tag 视图的标签值,默认是0,建议设置在100以上,根据这个值可以在父视图中查找该视图,(默认值是0啊笨蛋)
6、exclusiveTouch 默认为No,exclusiveTouch的意义在于:如果当前设置了exclusiveTouch的UIView是整个触摸事件的第一响应者,那么到你所有的手指离开屏幕前其他的UIView是无法接受到整个事件周期内所有的触摸事件。
7、frame 位置和尺寸
8、center 中心点
9、bounds 只能修改尺寸
10、transform 形变状态(平移、旋转、缩放),带make以原始形态进行改变,不带make则以指定形态进行改变
11、superview 父视图(只读)
12、subviews 子视图(数组)
13、window 所在窗口(只读)
(重要)获取根视图的superview和window时,需要注意,在viewdidload中是获取不到的,viewdidload只是视图加载完成,并没有添加到窗口中,因此需要在viewDidAppear方法中才能获取到。那时候视图才被添加到窗口中。
14、autoresizesSubviews 默认为YES,表示当父视图尺寸改变时,子视图也会随着改变,默认值是YES
15、autoresizingMask 默认为UIViewAutoresizingNone,不会自动伸缩。
16、contentMode 设置内容模式
UIViewContentModeScaleToFill 不等比填充满
UIViewContentModeAspectToFill 等比填充满,溢出
UIViewContentModeAspectToFit 等比,留白
17、backgroundColor 背景颜色,默认是nil
18、添加子视图方法 addSubview: bringSubviewToFront: sendSubviewToBack: removeFromSuperview insertSubview:atIndex:
insertSubview:aboveSubview: insertSubview:belowSubview: exchangeSubviewAtIndex:withSubviewAtIndex:
19、是否裁剪超出视图部分当子视图
view.clipsToBounds = YES;layer.cornerRadius
三、生命周期
1、创建载入跟视图 loadView
2、视图载入完成 viewDidLoad
3、视图将出现在屏幕之前 viewWillAppear
4、视图已经在屏幕上渲染完成 viewDidAppear
5、视图将要在窗口上移除之前 viewWillDisappear
6、视图已经从屏幕上移除 viewDidDisappear
7、接受到内存警告
}
UIView的部分圆角问题
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(120, 10, 80, 80)];
view2.backgroundColor = [UIColor redColor];
[self.view addSubview:view2];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view2.bounds byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(10, 10)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = view2.bounds;
maskLayer.path = maskPath.CGPath;
view2.layer.mask = maskLayer;
//其中,
byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
//指定了需要成为圆角的角。该参数是UIRectCorner类型的,可选的值有:
* UIRectCornerTopLeft
* UIRectCornerTopRight
* UIRectCornerBottomLeft
* UIRectCornerBottomRight
* UIRectCornerAllCorners
==================================================================================================================================================
{
😀、AVAudioPlayer
注意:
1.需要导入#import
2.定义的对象需要定义成全局
一、AVAudioPlayer的使用,只能播放本地音视频
1、获取路径
NSString *urlPath = [[NSBundle mainBundle] pathForResource:@"test.mp3" ofType:nil];
2、将路径转化成URL
NSURL *url = [NSURL URLWithString:urlPath];
3、实例化播放器(全局)
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
4、准备播放
[_audioPlayer prepareToPlay];
5、播放
[_audioPlayer play];
6、其他属性、方法
.currentTime 实时时间
.duration 持续时间
.numberOfLoops 循环次数
-pause 暂停
-stop 停止
7、停止后执行的方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {}
二、AVPlayer的使用,可播放本地和网络音视频
1、实例化播放器对象,并赋予路径
_avPlayer = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:@"http://mp3.qqmusic.cc/yq/5023716.mp3"]];
2、开始播放
[_avPlayer play];
三、播放系统声音
添加全局变量
SystemSoundIDsoundID;//系统声音标识符
1、获取本地声音文件
NSString *sysPath = [[NSBundle mainBundle]pathForResource:@"44th Street Medium.caf" ofType:nil];
2、将路径转换成URL
NSURL *sysUrl=[NSURL fileURLWithPath:sysPath];
3、注册声音成为系统声音
__bridge桥接 让ARC管理CF框架的内存释放
CFArrayRef -->NSArray
CFStringRef -->NSString
AudioServicesCreateSystemSoundID((__bridge CFURLRef)sysUrl, &soundID);
4、播放系统声音
AudioServicesPlaySystemSound(soundID);
5、播放震动只能真机演示
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
6、暂停系统声音 还可以继续播放
AudioServicesDisposeSystemSoundID(soundID);
7、完全停止系统声音
AudioServicesRemoveSystemSoundCompletion(soundID);
}
==================================================================================================================================================
{
😊、多线程
注意:
1.一个应用可以有多个进程,一个进程包含多个线程
2.同步、异步、阻塞、非阻塞、死锁、互斥锁、信息量
3.并发:两个人拿着一把铲挖一个坑
并行:两个人拿着两把铲挖一个坑
并行一定并发,并发不一定并行
4.一个程序有且只有一个主线程, 串行的,与应用程序绑定
5.任何能够阻塞主线程的任务都不因该放在主线程
6.cancel只有一个作用:把某个开启的线程标志为取消状态
如果一个线程刚开启就标志位取消状态,那么这个线程会被杀死,节约系统资源
exit退出一个线程
7.一个线程所占内存是固定的,主线程1M,多线程512kB,所以不能无限开启多线程
8、线程池:多线程创建出来后会被放到线程池,需要用时在池中取
9、多线程实现的是提高了资源的使用率
10、主线程:用户触摸、滑动事件、UI相关操作必须放在主线程,只有主线程有直接修改UI的能力
多线程:耗时的操作一定不能放在主线程
不能在子线程中更新UI,因为属性都是非线程保护的,多个线程可以同时访问此资源,如果同时更新同一个UI空间,可能会到时花屏
11、线程的状态:新-可运行=运行-死
12、同步不会开启新的线程
异步会开启新的线程
13、
一、NSThread
1.直接使用NSThread创建多线程 + 开启
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(thread1) object:nil];
[thread1 start];
(常用)2.直接使用类方法创建多线程 不需要开启(分离线程)
[NSThread detachNewThreadSelector:@selector(test) toTarget:self withObject:nil];
3.通过NSObject提供的类目创建多线程序
[self performSelectorInBackground:@selector(test) withObject:nil];
4.创建一个子类继承雨NSThread,要通过start开启子类线程来实现多线程,复写main方法,是线程的主题方法,不能直接调用main方法,直接调用是普通的对象调用父类实例方法,不是多线程
-currentThread 当前线程
+isMainThread 是否是主线程
+isMultiThread 是否是多线程
+sleepForTimeInterval 睡眠几秒
+exit 退出线程(应该退出已经标志为取消状态的进程)
+setThreadPriority 设置线程优先级(没有开启之前设置,默认0.5,主线程开启优先级就确定,无法修改)
.name 设置线程名称
.executing 是否正在执行
.finished 是否已经结束
.cancelled 是否是取消(状态)
.threadPriority 线程优先级(float)
二、线程的状态 (NSThread一个线程只能开启一次)
1、创建线程对象 新建状态
2、开启线程 就绪状态
3、调用方法 运行状态
4、方法结束 死亡状态
5、在支线程设置runloop,保证线程不死王
三、线程通信
(重要)1、在支线程中要注意内存管理,开启一个自动释放池,将带吗放到自动释放池中
2、切换到主线程中,将数据传过去
方法一、
[self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];
方法二、
[self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
方法三、
[_imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
NSOperation 操作任务,一般情况下使用它的子类
一、NSBlockOperation
1、创建,并在block中定义任务
NSBlockOperation *_blockOperation = [NSBlockOperation blockOperationWithBlock:^{}];
2、执行任务,位置决定了是否是在支线程
[_blockOperation start]
二、NSOperationQueue
1、创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
2、将任务添加到队列中,自动执行任务,执行的顺序跟数组的次序一致,但只是在并发数唯一的情况下
[queue addOperations:@[blockOperation1,blockOperation2,blockOperation3,blockOperation4] waitUntilFinished:YES];
3、设置任务的优先级,影响的是CPU分配给当前任务的事件多少(必须在添加到队列之前设置,枚举)
blockOperation1.queuePriority = NSOperationQueuePriorityVeryHigh;
4、设置最大并发数(为1会使线程变成2,为2可看出线程重复利用)
queue.maxConcurrentOperationCount = 2;
5、队列中开启的线程可以重复使用
(重要)6、依赖关系 (前依赖后)
[blockOperation4 addDependency:blockOperation2];
三、NSInvocationOperation
1、创建
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(fun)
object:nil];
2、开启(在当前线程)
3、加在队列中(多线程)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:invocationOperation];
4、获取主队列
5、在主队列中添加线程,就可以将信息UI传回主线程(block)
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
四、锁 互斥锁、递归锁、分布锁 让一块内存空间在一个时间内只能被一个对象修改
加了锁之后,同时只能有一个线程访问此资源
如果不加锁,在延迟的时间里 如果有其他线程访问此资源就可能出现-到负数的情况
当第一个线程访问此资源时,当其他线程访问此资源时需要等待
(重要)1、创建锁对象(全局)
_lock = [[NSLock alloc] init];
2、加锁 保证资源只能被同一个线程修改,一个资源只能加一次锁,加两次以上会锁死
[_lock lock];
3、要锁的内容
4、解锁
[_lock unlock];
5、类似自动释放池的锁
@synchronized(self){ 要锁的内容 }
}
==================================================================================================================================================
{
😉、GCD(Grand Central Dispatch) 大型任务分发中心
1.优点:纯C编写,易用、效率、性能、安全。
2.Dispatch Queue 串行、并行、主队队列,所有主队列的任务都在主线程。
全局队列(多线程)、串行队列(有可能是多线程,取决于它在哪个线程)
3.同步:提交任务必须等待任务完成,才可继续提交
异步:提交任务不需要完成,就可以继续提交
串行队列:一个任务执行完,下一个任务才可以执行
并发队列:一个任务没有执行完,也可以执行下一个任务
一、GCD的使用
1.创建串行队列(单个线程) 参数1 字符串队列的名称(id+项目名+名字) 参数2 队列的类型
dispatch_queue_t queue1 = dispatch_queue_create("queue1", NULL);
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL);
2.创建并发队列(多个线程) 第二个参数只能使用给定的宏
dispatch_queue_t queue3 = dispatch_queue_create("queue3", DISPATCH_QUEUE_CONCURRENT);
3.获取全局队列 运行在全局队列中的任务,必定是在多线程中 特殊的并发队列,一般的多线程都使用这个
第一个参数 全局队列的优先级(高、默认、低、后台)
第二个参数 是API留作未来使用,默认0
dispatch_queue_t globaQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
4.获取主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
二、提交任务
(重点)1.同步提交 需要等待,提交到哪个线程,就公用哪一个线程
dispatch_sync(serialQueue, ^{ 任务内容 });
2.异步提交 提交到串行队列:谁先提交谁先执行,使用单个线程
提交到并发队列:多线程,先提交不一定先执行完,提交没有执行完,后面的任务可以继续提交
dispatch_async(concurrentQueue, ^{ 任务内容 });
3.间隔2s之后向主线程提交一个任务
4.使用GCD创建单例
+ (instancetype)shareInstance {
//把onceToken当做布尔值来用,判断onceToken是否是yes,如果是就不执行,如果不是就执行
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init]; });
return instance;
}
5、数据返回主线程(更新UI)在GCD中嵌入GCD
三、死锁 使用同步提交的方式提交到主线程一个任务
原因:本次任务还未完成还要给主线程(串行)添加任务,那么本身的任务永远完成不了
解决办法:不要把它放到主线程,放到多线程
建议:不要使用同步提交方式
三、Dispatch Group (重要) 无法取消
1.创建队列和group对象
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
2.往group添加任务 参数:group对象 队列 任务
dispatch_group_async(group, queue, ^{ });
3.汇总任务一 参数:droup对象 队列 不会阻塞主线程 所有任务完成后调用
相当于监听,前面任务完全完成后在执行
dispatch_group_notify(group, queue, ^{ });
汇总任务二 参数:参照时间 时间(微秒,秒,纳秒) 设置等待时间 是在主线程进行,会阻塞当前线程
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
long result = dispatch_group_wait(group, time);
if(result == 0) {所有任务都已完成} 返回其他数值,没有执行完,超时
四、NSRunLoop
1.线程的5个状态:新建、就绪、运行、阻塞、死亡
2.开RunLoop是为了能让程序处在活跃状态
3.开启一个新的线程,不会把定时器添加到当前RunLoop中
4.开启新的线程需要手动开启runloop
5.定时器不精准,很有可能卡死
6.手机屏幕刷新率60次/s,获取屏幕刷新率对象,模拟器没有刷新率
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayMethod)];
添加到世界循环
[link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
屏幕梅刷新一次就会调用一次displayMethod,可以设置一个全局变量value来控制事件
五、Dispatch_once_t 标签变量
1、创建标签变量
static dispatch_once_t onceToken;
2、把需要标志的操作放进去,保证只执行一次
dispatch_once(&onceToken, ^{
//这里的操作只会执行一次
});
3、用法:创建单例(三个方法)
召唤:dispatch_once
六、延时调用
1、创建延时时间 时间参考点 指定的时间
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);
2、调用GCD延时函数
dispatch_after(time, dispatch_get_global_queue(0, 0), ^{ 要执行的操作 });
3、在哪个线程开启,就在那个线程挂起
[self performSelector:@selector(delayAction) withObject:nil afterDelay:5];
4、取消挂起的方法
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(delayAction)
object:nil];
七、GCD遍历数组
1、枚举器遍历
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%ld %@ ", idx, obj);
}];
2、Dispatch_Apply(多线程遍历,哪个闲置用哪个,多个线程)
//Dispatch_Apply遍历
使用GCD实现遍历 充分利用多线程的性能 必须放到全局队列中
把循环的每次迭代提交到queue中执行, 将循环的任务追加到队列中 如果是并行队列
就会开启多线程 在后台线程中执行
参数1:数组的元素个数
参数2:指定的队列
参数3:表示循环到第几次 无符号长整形
dispatch_apply(array.count, dispatch_get_global_queue(0, 0), ^(size_t index) {
NSLog(@"%ld %@", index, array[index]);
});
八、精准定时器
1、主线程中开启的定时器会阻塞线程,UI界面的操作会影响主线程,导致卡顿现象,定时器不会调用方法
解决:使用添加到事件循环,comment模式
2、在支线程中开启+开启事件循环,防止线程死掉
//定时器二
NSTimer *timer = [NSTimer timerWithTimeInterval:1
target:self
selector:@selector(timerAction:)
userInfo:nil
repeats:YES];
//模式选择NSRunLoopCommonModes
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
定时器不使用时,应该使其失效,并置空
[_timerinvalidate];
_timer=nil;
3、精准定时器 利用频幕的刷新率 也会阻塞 利用屏幕的刷新率 60HZ 每刷新一次调用一次绑定的方法
frameInterval 每隔多少帧调用一次
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timerAction:)];
link.frameInterval = 60;
[link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
==================================================================================================================================================
{
😍、网络编程
一、http协议 超文本传输协议
1.请求方式:GET请求、POST请求
2.请求包结构:请求头、请求体(GET只有请求头)
3.请求头类似于字典
4.状态码,表示响应结果,4开头都是服务器有问题
5.响应头中的Content-Type表示响应体中的数据类型
6.同步请求:在主线程进行,会导致只线程阻塞
异步请求:多线程进行
UI界面的渲染与刷新在主线程中进行,主线程不流畅会导致UI界面卡顿
7.C\S 客户端 <- 连接通道 -> B\S 服务器端
8、服务器端开发语言:Java .Net PHP C/C++ Ruby Python
9、客户端与服务器端的数据传输,数据必须约定使用同一种格式,例如:json、xml <—>二进制
10、HTTP协议:超文本传输协议、国际通用协议,浏览器和服务器之间的通信规则
11、客户端 ———————请求包——————> 服务端
<——————响应包——————
12、GET请求:向服务器索取数据(请求头)
POST请求:向服务器提交数据(请求头、请求体)
13、请求头:描述所请求的数据
14、响应包
响应头:描述我想要的数据(返回的)是数据样子
响应体:我们所需要的东西
15、豆瓣API 主接口+子接口
16、请求头拼接参数 接口?key=value&key=value&key=value
Request Properties 认可的参数列表
17、URL 资源定位符,接口
18、步骤:(修改plist文件)NSURL-NSURLRequest-NSURLSessionCongiguration(可选)-NSURLSession-NSURLSessionDataTask-执行
19、session类型
默认:持久化,基于磁盘缓存
临时:内存中
后台
20、无名拼接、json拼接
21、data转换成string
二、网络组件 NSURLSession <<五步走>>
1.构建NSURL实例
NSURL *url = [NSURL URLWithString:@"https://api.douban.com/v2/movie/top250"];
2.构建NSURLRequest对象(默认GET请求),设置请求配置 (url对象,缓存策略,超时时间)
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60];
3.创建网络会话,单例对象
NSURLSession *session = [NSURLSession sharedSession];
4.使用会话对象发送网络请求 返回值是会话任务对象 (服务器发给响应体的二进制数据,响应头数据)(在多线程)
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 解析二进制数据
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:nil];
NSLog(@"%@", dic); //解析后的数据
NSLog(@"%@", response); //请求头的数据
//NSLog(@"%@", data); //未解析的二进制数据
}];
5.执行任务
[task resume];
三、GET请求 (异步发送的请求,多线程)
1.创建URL对象 带参数的GET请求
NSURL *url = [NSURL URLWithString:@"https://api.douban.com/v2/movie/top250"];
2.创建request对象 这个设置的参数较少,不好
建议使用它的子类NSMutableURLResquest
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//缓存策略
[request setCachePolicy:NSURLRequestUseProtocolCachePolicy];
//超时时间
[request setTimeoutInterval:120];
//请求方式(默认是GET请求)
[request setHTTPMethod:@"GET"];
//HTTPBody 请求体
//HTTPHeader 请求头
3.NSURLSession
NSURLSession *session = [NSURLSession sharedSession];
4.task
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//容错
if (error == nil) {
//对比NSURLResponse和NSHTTPURLResponse(状态码、响应头)
NSLog(@"response = %@", response);
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"httpRespomse = %ld", (long)httpResponse.statusCode); //状态码
NSLog(@"httpRespomse = %@", httpResponse.allHeaderFields); //响应头
//error容错判断 和 NSRerror
NSError *jsonError = nil;
[NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&jsonError];
if (jsonError) {
NSLog(@"jsonError = %@", jsonError);
}
}
}];
//5.设置plist文件 App Transport
[task resume];
//6.(警告)刷新UI
dispatch_sync(dispatch_get_main_queue(), ^{
//UI部分就写在这
});
四、POST请求
微博API-开放平台-API文档-接口测试
1.url 网址先测试,再使用 参数拼接顺序不影响结果,
NSURL *url = [NSURL URLWithString:@"https://api.weibo.com/2/statuses/update.json"];
2.request 使用子类的
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
超时时间
[request setTimeoutInterval:120];
请求方法类型
[request setHTTPMethod:@"POST"];
(重要)请求体,接口是已经登录的微博的接口(俩个参数是必须的)
NSString *bodyString = @"access_token=2.00f3FX5GLS4fbC3e06717e8d09Abdi&status=有一种孤独,叫我还未成年";
转换成二进制数据
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:bodyData];
3.session 单例
NSURLSession *session = [NSURLSession sharedSession];
4.task 发送请求
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data,NSURLResponse * _Nullable response, NSError * _Nullable error) {
响应头
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"%ld", httpResponse.statusCode);
}];
5.执行任务
[task resume];
四、懒加载 用到的时候才加载
1.不生成get、set方法 @dynamic
生成get、set方法 @synthesize
2.实际就是一个get方法
- (NSArray *)paths {
if (paths == nil) {
paths = [NSArray array];
}
return paths;
}
五、NSURLSession指的是一个网络会话,一个会话可以发起多个任务,一个任务对应一次网络请求
1.Session类型:默认、临时、后台(退出后台仍然能够下载,下载完后重新打开程序)
六、NSURLSessionConfigration用于配置Session对象
1.url
NSURL *URL = [NSURL URLWithString:@"https://api.douban.com/v2/movie/coming_soon"];
2.urlResquest 如果POST请求,需要创建Resquest对象,设置请求体
3.创建configuration(默认、临时、后台)
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
超时时间(默认60s)
configuration.timeoutIntervalForRequest = 120;
设置是否可以使用蜂窝数据
configuration.allowsCellularAccess = YES;
4.Session (不能使用单例,应该使用代理方式创建,创建在哪个线程)
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:[NSOperationQueue mainQueue]]; //创建在主线程
5.发送请求,返回task
NSURLSessionDataTask *task = [session dataTaskWithURL:URL];
6.执行请求
[task resume];
7.实现协议方法
(1)、接收到响应头会调用(多次),需要调用block,传递allow参数
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"response.statuscode = %ld", httpResponse.statusCode); //打印状态码
}
(2)、数据请求完毕调用的协议方法(数据反回调用的方法)上面的方法复写后,此方法不会被调用,要想调用这个方法,那么必须在上个方法调用block(重要)。
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
id result = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:nil];
NSLog(@"%@",result);
}
(3)、数据传输完成之后调用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask {
//查看是否是在主线程
NSLog(@"%d", [[NSThread currentThread] isMainThread]);
}
(4)、请求完成后,不管失败,还是成功都会调用的方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
// NSLog(@"%@", error);
}
七、上传数据
1、URL
NSURL *url = [NSURL URLWithString:@"https://upload.api.weibo.com/2/statuses/upload.json"];
2、设置请求方式:POST
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
3、设置请求头
NSString *headerString = [NSString stringWithFormat:@"multipart/form-data; charset=utf-8;boundary=%@", boundary];
[request setValue:headerString forHTTPHeaderField:@"Content-Type"];
4、构造请求体:(1)、access_token (2)、status (3)、pic
百分号%% 双引号\” \”
NSMutableString *mBodyString = [NSMutableString string];
[mBodyString appendFormat:@"--%@\r\n", boundary];
[mBodyString appendFormat:@"Content-Disposition: form-data; name=\"access_token\"\r\n\r\n"];
[mBodyString appendFormat:@"2.00bEgIqC0ll_TLe543cd66dc07uEQR"];
[mBodyString appendFormat:@"--%@\r\n", boundary];
[mBodyString appendFormat:@"Content-disposition: form-data; name=\"status\"\r\n\r\n"];
[mBodyString appendFormat:@"撒卢卡\r\n"];
[mBodyString appendFormat:@"--%@\r\n", boundary];
//拼接图片数据
[mBodyString appendFormat:@"Content-disposition: form-data; name=\"pic\"; filename=\"这个名字是随意的\"\r\n"];
[mBodyString appendFormat:@"Content-Type: application/octet-stream\r\n\r\n"];
NSData *data = [mBodyString dataUsingEncoding:NSUTF8StringEncoding];
NSData *imageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"timg.jpg" ofType:nil]];
NSMutableData *mdata = [NSMutableData data];
[mdata appendData:data];
[mdata appendData:imageData];
NSString *endString = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary];
[mdata appendData:[endString dataUsingEncoding:NSUTF8StringEncoding]];
//请求体
request.HTTPBody = mdata;
5、创建会话
NSURLSession *session = [NSURLSession sharedSession];
6、根据会话创建任务,上传数据
NSURLSessionDataTask *task = [session uploadTaskWithRequest:request fromData:mdata completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSLog(@"success");
};
}];
7、执行任务
[task resume];
八、下载数据(不能实时监听)
1、URL
2、session
3、创建网络任务(收到的数据:文件的沙盒路径、请求头、error)
先是存在tmp临时文件夹,如果不将它存到自己的文件夹,出了block之后就会被删除
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//blcok 下载完毕之后在调用,不能实时监听
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/后会无期.mp3"];
NSLog(@"%@",filePath);
NSURL *url = [NSURL fileURLWithPath:filePath];
//location文件的位置,下载后无法储存文件,(临时的文件,)block代码块执行完毕,
//文件会被删除
BOOL isScuess= [[NSFileManager defaultManager]copyItemAtURL:location toURL:url error:nil];
if (isScuess) {
NSLog(@"下载成功");
}
}];
4、拷贝一份下载的数据
九、下载任务(实时监听)
1、URL
NSURL *url = [NSURL URLWithString:@"http://www.itinge.com/music/3/9158.mp3"];
2、创建一个会话配置对象configuration(默认、支持后台、)
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
3、利用configuration创建session,协议
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
4、创建下载任务(注意是下载任务)
NSURLSessionDownloadTask *dataTask = [session downloadTaskWithURL:url];
5、实现代理方法
(1)、正在下载(调用多次)
网络任务
网络会话
当前下载下来的数据
当前下载下载的总数据
文件总大小
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
self.processView.progress = (double)totalBytesWritten/totalBytesExpectedToWrite;
}
(2)、已经完成下载
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/后会无期.mp3"];
NSLog(@"%@",filePath);
NSURL *url = [NSURL fileURLWithPath:filePath];
//location文件的位置,下载后无法储存文件,(临时的文件,)block代码块执行完毕,
//文件会被删除
BOOL isScuess= [[NSFileManager defaultManager]copyItemAtURL:location toURL:url error:nil];
if (isScuess) {
NSLog(@"下载成功");
}
}
十、断点续传
1、取消任务,记录下载量
[_task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
//记录暂停时的下载位置,指示标志一下,并不是真是下载量
_data = resumeData;
}];
2、根据下载量构造全新任务
//根据断点重新构造任务
_task = [_session downloadTaskWithResumeData:_data];
[_task resume];
十一、后台下载
1、将configuration修改为后台下载
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"CYC666"];
十二、封装网络请求
1、自定义的类方法
+ (void)requestWithUrl:(NSString *)url httpMethod:(NSString *)method pamaleter:(NSMutableDictionary *)pamaleter; {
//1、构建URL
NSURL *requestUrl = [NSURL URLWithString:url];
//2、构建请求request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestUrl];
//3、设置请求方式
request.HTTPMethod = method;
//4、拼接参数
NSMutableString *mString = [NSMutableString string];
NSArray *keys = [pamaleter allKeys];
for (int i = 0; i < pamaleter.count; i++) {
NSString *key = keys[i];
NSString *value = pamaleter[key];
[mString appendFormat:@"%@=%@", key,value];
//最后一个参数不需要拼接&
if (i <= pamaleter.count-1) {
[mString appendFormat:@"&"];
}
}
if ([method isEqualToString:@"GET"]) {//GET请求
//判断URL后面是否拼接有参数,有则拼&,无则拼?
NSString *seper = requestUrl.query ? @"&" : @"?";
url = [NSString stringWithFormat:@"%@%@%@", url, seper, mString];
//重新设置一下url(因为url重新拼接了)
request.URL = [NSURL URLWithString:url];
} else {
//设置请求体
request.HTTPBody = [mString dataUsingEncoding:NSUTF8StringEncoding];
}
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSLog(@"success!");
};
}];
[task resume];
}
2、调用
//拼接参数
NSDictionary *dic = @{
@"access_token":@"2.00BSUoQClB87iBba5e1aa3331qYmpC",
@"status":@"你的嗓音就是世界的祸害"
};
[CYCNetService requestWithUrl:@"https://api.weibo.com/2/statuses/update.json"
httpMethod:@"POST"
pamaleter:[dic mutableCopy]];
十三、AFNetworking 从github获取第三方框架
1、简单的GET请求
(1)、URL
NSString *urlStr = @"http://piao.163.com/m/cinema/list.html?apiVer=6&city=110000";
(2)、manager对象 用来管理网络请求
AFHTTPSessionManager *manager=[AFHTTPSessionManager manager];
(3)、发送GET请求(主线程!!!!!)
[manager GET:urlStr parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
//默认解析json类型
NSLog(@"responseObject = %@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error = %@",error);
}];
2、简单的POST请求
(1)、URL
(2)、manager对象
AFHTTPSessionManager *manager=[AFHTTPSessionManager manager];
(3)、拼接参数
NSDictionary *dic=@{@"cinema_id":@1533};
(4)、默认是以拼接类型上传给服务器 默认解析为json类型
A、告诉服务器以拼接类型来解析客户端传给服务器的数据,拼接类型
AFHTTPRequestSerializer *jointSerializer=[AFHTTPRequestSerializer serializer];
manager.requestSerializer=jointSerializer;
B、告诉服务器以json类型来解析客户端传给服务器的数据
json 字典类型{"cinema_id" : 1533} 数组类型[]
AFJSONRequestSerializer *jsonSerializer=[AFJSONRequestSerializer serializer];
manager.requestSerializer=jsonSerializer;
(5)、服务器返回给客户端时,你需要解析的数据类型
A、服务器返回的数据不解析
AFHTTPResponseSerializer *responserSer=[AFHTTPResponseSerializer serializer];
manager.responseSerializer=responserSer;
B、可以解析为json类型
AFJSONResponseSerializer *jsonResponserSer=[AFJSONResponseSerializer serializer];
manager.responseSerializer=jsonResponserSer;
C、如果可以解析为XML类型才可以设置 如果不支持解析为xml类型那么默认不解析
AFXMLParserResponseSerializer *xmlPar=[AFXMLParserResponseSerializer serializer];
manager.responseSerializer=xmlPar;
D、直接解析为一个UIImage对象
AFImageResponseSerializer
(6)、发送请求
[manager POST:str parameters:dic success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
//responseObject 最终返回的响应体数据
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error = %@",error);
}];
3、发送图片微博
(1)、manager对象
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
(2)、拼参数
NSDictionary *parameters = @{@"access_token" : @"2.00f3FX5GLS4fbC3e06717e8d09Abdi",@"status" : @"天气很凉爽"};
(3)、发送POST请求
[manager POST:@"https://upload.api.weibo.com/2/statuses/upload.json" parameters:parameters constructingBodyWithBlock:^(id _Nonnull formData) {
A、获取图片数据
NSData *imageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"test.jpg" ofType:nil]];
B、上传的图片数据拼接在formData中
[formData appendPartWithFileData:imageData name:@"pic" fileName:@"file" mimeType:@"image/jpeg"];
}
success:^(NSURLSessionDataTask *_Nonnull task,id _Nonnull responseObject) {
NSLog(@"上传成功");
}
failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
NSLog(@“失败”);
}
];
4、下载任务
(1)、manager
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
(2)、URL
NSURL *url = [NSURL URLWithString:@"http://mp3.qqmusic.cc/yq/5023716.mp3"];
(3)、构建request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
(4)、下载请求
NSProgress *progress = nil; //把NSProgress对象存在progress中
NSURLSessionDownloadTask *task = [manager downloadTaskWithRequest:request progress:&progress
destination:^NSURL *_Nonnull(NSURL *_Nonnull targetPath, NSURLResponse *_Nonnull response) {
A、targetPath是一个临时保存在本地磁盘的位置
NSLog(@"targetPath = %@", targetPath);
B、文件在沙盒中保存的位置
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/wake(live).mp3"];
C、block有返回值 文件需要保存的位置
return [NSURL fileURLWithPath:path];
}
completionHandler:^(NSURLResponse *_Nonnull response, NSURL *_Nullable filePath, NSError *_Nullable error) {
NSLog(@"filePath = %@", filePath);
}
];
(5)、执行任务
[task resume];
十四、XML 一种存储数据的格式
一、文档声明、元素节点、属性
二、解析方式:DOM、SAX(一边读取一边解析)
三、第三方框架:NSXMLParser(最慢)、libxml2、TBXML(最快,轻量)、、、KissXML
四、拼接XML
1、添加编译文件libxml2.2.tbd
build phases -> link binary with libraries + libxml2.2.tbd
2、添加KissXML第三方框架
3、导入头文件
#import "DDXML.h"
4、添加路径
header search paths -> debug + any architecture|any SDK + user/include/libxml2
五、解析XML
1、DOM解析方式(主流)、SAX解析方式(实时解析,适合大数据)
2、读取整个xml文档
3、获取子节点
4、for-in遍历获取节点值
定点查询
未知查询
分支查询(下标从1开始)
六、NSURLConnection
一、同步
//1、URL
NSURL *url = [NSURL URLWithString:@"http://api.douban.com/v2/movie/top250?count=30"];
//2、请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//3、响应头
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//4、解析数据
id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@", result);
二、异步
NSURL *url = [NSURL URLWithString:@"http://api.douban.com/v2/movie/top250?count=30"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(@"%@", [NSThread currentThread]);
id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@", result);
}];
七、网络状态监测
1、在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 监听
2、添加AFNetworking框架,导入头文件
3、创建全局manager
4、开始监听
5、状态检测block,每当状态改变就会调用block
}
=================================================================================================================================================
{
😍、绘图与文本
1.Quartz 2D API,基于路径的绘图、透明度、阴影、颜色管理、反锯齿、PDF
2.Core Graphics框架,Quartz 2D引擎。
3.Quartz 2D与分辨率和设备无关,无需考虑最终绘制目标的设备
4.Core Garlic框架是基于C的API
5.UIKit依赖于Core Graphics,当引入UIKit时,CG框架会被自动引用
6.UIKit内部封装了CG的一些API
7.Graphics Context相当于画布,有很多类型
8.Quartz的所有对象都华画在Graphics Context中
9.定义UIView,实现drawRect方法,如果复写了又不实现任何功能,做动画会极大地影响性能
10.调用自定义的drawRect后,视图对象自动配置绘图环境以便能立即绘图操作
11.通过UIGraphicsGetCurrentContext()方法获取当前的Graphics Context
12.Quartz 默认原点在左下角
13.只能在drawRect中获取CGContextRef进行绘图,在其他方法获取的CGContextRef不能用于绘图.
如果一定要在其他方法中使用CGContextRef绘图,那必须要在drawRect中调用方法,并将CGContextRef传递过去
14.使用含有creat、copy函数创建对象,使用完后必须释放,否则将导致内存泄漏
15.路径属于绘图信息,。。。属于绘图状态
一、Quartz 2D
1.创建子类化UIView的类化
2.在子类中复写drawRect方法
3.获取系统已经创建好的Context(这个东西系统会自动帮我们创建)
CGContextRef contextRef = UIGraphicsGetCurrentContext();
4.创建路径
UIBezierPath *path = [UIBezierPath bezierPath];
5.添加到上下文
CGContextAddPath(contextRef, path.CGPath);
6.绘制路径
CGContextStrokePath(contextRef);
7、设置线条终点形状
CGContextSetLineCap(ref, kCGLineCapRound);
8、设置虚线
float lengths[] = {15,10}; //15表示实线长度,10表示虚线长度
CGContextSetLineDash(context, 0, lengths,2); //上下文、(写0就好)、数组、数组长度
9、设置透明度
CGContextSetAlpha(ref, .5);
10、修改画布坐标系
CGContextRotateCTM(contextRef, M_PI); //旋转
CGContextTranslateCTM(contextRef, 0, -rect.size.height); //平移
CGContextScaleCTM(contextRef, -1, 1); //缩放
11、设置阴影
CGContextSetShadow(ref, CGSizeMake(10, 20), 5); //阴影当偏移、羽化大小,这个方法默认黑色阴影
CGContextSetShadowWithColor(ref, CGSizeMake(10, 20), 5, [UIColor yellowColor].CGColor); //可以自定义阴影颜色
12、设置线宽
CGContextSetLineWidth(ref, 5);
13、设置线条颜色
[[UIColor orangeColor] setStroke];
14、设置填充颜色
[[UIColor yellowColor] setFill];
线条的类型
path.lineCapStyle=kCGLineCapRound;
15、(重要)当需要刷新绘制的图形时,相当于在当前视图添加了一个重绘标记,等到下一次屏幕刷新时,系统会创建好默认的上下文,然后调用drawRect
[self setNeedsDisplay];
二、水印
1.开启位图上下文,他就是一块内存区域
UIImage *image = [UIImage imageNamed:@"WeChatLaunch@3x.png"];
UIGraphicsBeginImageContext(image.size);
2.将图片添加到上下文
[image drawAtPoint:CGPointZero];
3.绘制文字水印
NSString *string = @"CYC666";
NSDictionary *dic = @{
NSFontAttributeName : [UIFont systemFontOfSize:30],
NSForegroundColorAttributeName : [UIColor redColor]
};
[string drawAtPoint:CGPointMake(image.size.width-200, image.size.height-50) withAttributes:dic];
4.从当前上下文中获取已经添加水印的图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
(重要)5.关闭位图上下文
UIGraphicsEndImageContext();
//将图片存入相册
UIImageWriteToSavedPhotosAlbum(newImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
三、图形的绘制
// 回执的时候必须使用这种方式,不能设置填充颜色
CGContextDrawPath(contextRef, kCGPathFillStroke);
kCGPathFill, // 填充,没有线条
kCGPathEOFill, // 只有线条
kCGPathStroke,
kCGPathFillStroke,// 线条➕填充
kCGPathEOFillStroke
//绘制三角形
//1.获取图形上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//2.创建路径
UIBezierPath *path = [UIBezierPath bezierPath];
//3.设置路径
[path moveToPoint:CGPointMake(30, 50)];
[path addLineToPoint:CGPointMake(200, 50)];
[path addLineToPoint:CGPointMake(200, 150)];
//将路径首尾连接
[path closePath];
//将路径添加到上下文
CGContextAddPath(contextRef, path.CGPath);
//填充颜色(黄色)
CGContextSetRGBFillColor(contextRef, 1, 1, 0, 1); 或 [[UIColor blackColor] setFill];
//线宽
CGContextSetLineWidth(contextRef, 1); 或 path.lineWidth
//路径颜色
[[UIColor orangeColor] setStroke];
//4.绘制路径
CGContextDrawPath(contextRef, kCGPathFillStroke);
//绘制圆形
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//center 中心点
//radius :半径
//startAngle 起始的角度
//endAngle 结束角度
//clockwise 是否顺时针
CGPoint center = CGPointMake(150, 300);
float radius = 100;
float startAngle = 0;
float endAngle = M_PI_2;
//创建圆形路径
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center
radius:radius
startAngle:startAngle
endAngle:endAngle
clockwise:YES];
//连接一条线到圆心,在结束角度添加
[path addLineToPoint:center];
//闭合路径,将路径收尾相连
[path closePath];
//将图路径添加到上下文
CGContextAddPath(contextRef, path.CGPath);
CGContextStrokePath(contextRef);
//绘制椭圆
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//创建路径,oval---椭圆
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40, 100, 300, 400)];
CGContextAddPath(contextRef, path.CGPath);
//描边路径
[path fill];
//画矩形
CGContextAddRect(ref, CGRectMake(10, 10, 150, 150));
四、图形上下文栈
1、在改变上下文时,保存一份上下文(保存到栈)
CGContextSaveGState(contextRef);
2、绘图,但是改变不了栈中的上下文状态
3、取出栈中的上下文(绘图状态没有改变)
CGContextRestoreGState(contextRef);
五、矩阵操作
1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//修改坐标系
CGContextRotateCTM(contextRef, M_PI); //旋转
CGContextTranslateCTM(contextRef, 0, -rect.size.height); //平移
CGContextScaleCTM(contextRef, -1, 1); //缩放
2.绘制图片
CGContextDrawImage(contextRef, CGRectMake(0, 0, 100, 100), image.CGImage);//没有经过修改的坐标系是倒置的
六、图片剪切
1.开启位图上下文
UIGraphicsBeginImageContext(image.size);
2.设置剪裁路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
3.将路径设置为剪裁路径
[path addClip];
4.将图片描绘在上下文
[image drawAtPoint:CGPointZero];
5.从位图上下文取出图片,图片已经剪裁好
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
}
==================================================================================================================================================
、正则表达式
一、基本语法
1.0\d{2}-\d{8}。这里\d后面的{2}({8})的意思是前面\d必须连续重复匹配2次(8次)。
2.\b代表着单词的开头或结尾,也就是单词的分界处。
3.\d是个新的元字符,匹配一位数字(0,或1,或2,或……)
4.匹配没有预定义元字符的字符集合,[.?!]匹配标点符号(.或?或!)。
5.\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符
[a-zA-Z] 表示小写字母或大写字母
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
二、在Xcode中的使用
1、导入第三方框架
RegexKitLite-master
2、添加库文件
libicucore.tbd
3、将libicucore.tbd的编译环境改成ARC
-fno-objc-arc
4、导入头文件
#import "RegexKitLite.h"
5、具体步骤
(1)、定义正则表达式
NSString *regex = @"\\d{3,4}-\\d{7,8}"; // \\d{3,4}匹配3~4个数字
(2)、使用正则表达式对字符串进行筛选,筛选结果存入数组中
NSArray *result = [text1 componentsMatchedByRegex:regex];
三、经典用法
1、检测微博用户
NSString *regex = @"@[\\w-]{2,30}";
2、检测QQ
NSString *regex4 =@"^\\d{6,11}$";
3、检测话题
NSString *regex = @"#[^#]+#";
4、检测超链接
NSString *regex = @"http(s)?://([a-z0-9A-Z._-]+(/)?)*";
5、组合使用
NSString *regex = [NSString stringWithFormat:@"@[\\w-]{2,30}|#[^#]+#|http(s)?://([a-z0-9A-Z._-]+(/)?)*"];
}
==================================================================================================================================================
{
9、沙盒路径(SandBox)
一、沙盒里的文件夹包括:
1、Documents 用于存储用户数据,iTunes备份和恢复的时候会包括此目录,所以,苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下。
2、Library 包含两个子目录:Caches 和 Preferences。
Caches用来存放用户需要换成的文件。
Preferences是APP的偏好设置,可以通过NSUserDefaults来读取和设置。
3.tmp 用于存放临时文件,这个可以放一些当APP退出后不再需要的文件。
二、沙盒路径的获取
1.获取沙盒根目录
NSString *directory = NSHomeDirectory();
2.获取documents目录
第一个参数是说明获取Doucments文件夹目录,第二个参数说明是在当前应用沙盒中获取。
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
类似的还有 NSDocumentDirectory
NSLibraryDirectory
NSCachesDirectory
3.获取tmp路径
NSString *tmp = NSTemporaryDirectory();
三、NSFileManager文件操作
NSFileManager是一个单列类,也是一个文件管理器。可以通过NSFileManager创建文件夹、创建文件、写文件、读文件内容等等基本功能。
1、创建文件夹
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *newPath = [documentsPath stringByAppendingString:@"/new"];
BOOL isSuccess = [fileManager createDirectoryAtPath:newPath
withIntermediateDirectories:YES
attributes:nil
error:nil];
2、创建文件
NSString *iOStext = [documentsPath stringByAppendingString:@"/iOS.txt"];
BOOL isSuccess2 = [fileMafnager createFileAtPath:iOStext
contents:nil
attributes:nil];
3、写文件
NSString *string = @"CYC要666啦,什么梅你在哪";
BOOL isSuccess3 = [string writeToFile:iOStext
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
4.读文件
NSString *readString = [NSString stringWithContentsOfFile:iOStext
encoding:NSUTF8StringEncoding
error:nil];
5、判断文件是否存在
BOOL isSuccess4 = [fileManager fileExistsAtPath:iOStext];
6.计算文件大小(每个汉字、字母、符号为两个字节,最后加\0结束符,一个字节)
unsigned long long fileSize = [[fileManager attributesOfItemAtPath:iOStext error:nil] fileSize];
NSLog(@"fileSize = %lld", fileSize);
7. 计算整个文件夹中所有文件大小
unsigned long long folderSize = [[fileManager attributesOfItemAtPath:documentsPath error:nil] fileSize];
8.移动文件(相当于重命名咯)
NSString *moveToPath = [documentsPath stringByAppendingString:@"/new/iOS.txt"];
BOOL isSuccess6 = [fileManager moveItemAtPath:iOStext
toPath:moveToPath
error:nil];
if (isSuccess6) {
NSLog(@"文件移动成功");
} else {
NSLog(@"文件移动不成功");
}
9.将图片保存在沙盒路径中
UIImage *image = [UIImage imageNamed:@"Ahome_tab_icon_3@2x.png.jpg"];
NSData *data = UIImagePNGRepresentation(image);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *patha = [paths objectAtIndex:0];
NSString *imagePath = [patha stringByAppendingString:@"Ahome_tab_icon_3@2x.png.jpg"];
[data writeToFile:imagePath atomically:NO];
四、NSUserDefaults 系统提供的plist数据持久化单例类,将存储在NSuserdefaults中的数据写入了一个以Bundle Identifier命名的plist中。
(注意:需要使用自己的加密算法进行加密,在进行数据存储。)
1、添加数据
[[NSUserDefaults standardUserDefaults] setObject:authData forKey:@"SinaWeiboAuthData"];
2、删数据
[[NSUserDefaults standardUserDefaults]removeObjectForKey:@"userpwd"];
五、蓝色文件夹与黄色文件夹
1、蓝色文件夹存在bundle路径下,不能通过文件名直接获取文件,需要拼合路径
[NSBundle mainBundle].resourcePath //一级路径
[[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:themePath] //二级路径
. . .//依次拼接路径
2、获取文件
//plist文件
NSString *configPath = [[self themePath] stringByAppendingPathComponent:@"config.plist"];
_colorDic = [NSDictionary dictionaryWithContentsOfFile:configPath];
//获取image
NSString *filePath = [[self themePath] stringByAppendingPathComponent:imageName];
UIimage *image = [UIImage imageWithContentsOfFile:filePath];
3、红色文件夹的读取方式
//读取plist文件
NSArray *facePlistArr = [NSArray arrayWithContentsOfFile: [[NSBundle mainBundle]pathForResource:@"emoticons.plist" ofType:nil]];
}
==================================================================================================================================================
{
10、CALayer 负责显示,view接收事件
一、属性clipsToBounds
1、圆角
view.layer.cornerRadius = 100;
2、边框宽度,边框颜色
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth = 5;
3、阴影,阴影偏移大小,阴影半径(羽化)(注意:需要设置阴影不透明度)
view.layer.shadowOffset = CGSizeMake(-40, 60);
view.layer.shadowColor = [UIColor lightGrayColor].CGColor;
view.layer.shadowRadius = 5;
view.layer.shadowOpacity = .7;
(重点)4、imageView设置允许圆角裁剪YES,但是设置了之后就不能设置阴影了
imageView.layer.masksToBounds = YES;
imageView.layer.cornerRadius = 50;
二、独立
1、创建
CALayer *layer = [CALayer layer];
(重点)2、设置frame
ayer.frame = CGRectMake(150, 40, 100, 100);
layer.bounds = CGRectMake(0, 0, 100, 100); //前俩个数值是中心点
layer.position = CGPointMake(150, 100);
设置锚点 注意:(0,0) , (0,1) , (0.5,0.5)... 参考:http://www.cnblogs.com/acBool/p/5071397.html
layer.anchorPoint = CGPointMake(0,0);
3、设置背景颜色
4、添加到view.layer
[self.view.layer addSublayer:layer];
三、layer的动画 (加make的只实现一次效果,其实就是在原始位置进行动作 )
1、平移
layer.transform = CATransform3DMakeTranslation(0, 100, 0);
2、缩放
layer.transform = CATransform3DMakeScale(.5, .5, 1);
3、旋转(旋转的轴置为1)
layer.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
4、使用lvc设置动画(注意:用forKeyPath而不是forKey)
[layer setValue:@.5 forKeyPath:@"transform.scale.x"];
四、隐式动画 自建的layer是隐式动画,view自带的layer是显式动画
1、layer设置显示的内容,返回值是id,可以是一张图片
layer.contents = (id)[UIImage imageNamed:@"QQlogin60@2x.png"].CGImage;
五、截图
1、开启位图上下文
2、获取当前上下文,也就是位图上下文
3、设置裁剪区域
4、将视图的图层渲染到位图上下文
5、从上下文获取新的图片
}