1.HTTP和HTTPS
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,
HTTP端口80,HTTPS端口443
HTTP是无状态的,HTTPS是可进行加密传输、身份认证的,更加安全
HTTPS需要CA证书,需要费用
对称:双方公用一个密钥 如AES
非对称:有一对密钥,公钥和私钥。公钥随便发,私钥则只能自己保管不会发出去,如果一旦用其中一个私钥加密,只能用另一个才能解开。如RSA、DSA
通话过程
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
![](https://img.haomeiwen.com/i5654620/712a135eee72616c.gif)
(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
(5)Web服务器利用自己的私钥解密出会话密钥。
(6)Web服务器利用会话密钥加密与客户端之间的通信。
网络概述https://www.jianshu.com/p/b4250ba3ef12
1.当iOS程序中发生触摸事件后,系统会将事件加入到UIApplication管理的一个任务队列中
2.UIApplication将处于任务队列最前端的事件向下分发。即UIWindow。
3.UIWindow将事件向下分发,即UIView。
4.UIView首先看自己是否能处理事件,触摸点是否在自己身上。如果能,那么继续寻找子视图。
5.遍历子控件,重复以上两步。
6.如果没有找到,那么自己就是事件处理者。如果 7.如果自己不能处理,那么不做任何处理。
其中 UIView不接受事件处理的情况主要有以下三种 1)alpha <0.01
2)userInteractionEnabled = NO
3.hidden = YES.
用pointInside方法,在里面扩大bounds:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {CGRectbounds =self.bounds; bounds =CGRectInset(bounds,-10,-10);// CGRectContainsPoint判断点是否在矩形内returnCGRectContainsPoint(bounds, point);}
自定义Button,重写pointInside方法,
// //改变图片的点击范围- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {//控件范围宽度多40,高度20CGRectbounds =CGRectInset(self.bounds,-20,-20);NSLog(@"point = %@",NSStringFromCGPoint(point));UIBezierPath*path1 = [UIBezierPathbezierPathWithRect:CGRectMake(-20,0,40,120)];UIBezierPath*path2 = [UIBezierPathbezierPathWithRect:CGRectMake(self.frame.size.width -20,0,40,120)];if(([path1 containsPoint:point] || [path2 containsPoint:point])&&CGRectContainsPoint(bounds, point)){//如果在path区域内,返回YESreturnYES; }returnNO;}
事件传递的顺序和hittest 里面pointInside的执行顺序是反的, 比如现在有一个需求,一个按钮加在TabBar上,他的点击区域超过哟了tabbar如:
如果此时点击超过的部分,按钮是不响应的,tabbar的ponintInside方法返回的是nil,也就是这个触摸点不在tabbar上,这时候我们需要重写tabbar的hitTest方法
![](https://img.haomeiwen.com/i809937/14b4f239fba4c545.png)
//重写hitTest方法,去监听中间按钮的点击,目的是为了让凸出的部分点击也有反应- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event {//判断当前手指是否点击到中间按钮上,如果是,则响应按钮点击,其他则系统处理//首先判断当前View是否被隐藏了,隐藏了就不需要处理了if(self.isHidden ==NO) {//将当前tabbar的触摸点转换坐标系,转换到中间按钮的身上,生成一个新的点CGPointnewP = [selfconvertPoint:point toView:self.centerBtn];//判断如果这个新的点是在中间按钮身上,那么处理点击事件最合适的view就是中间按钮if( [self.centerBtn pointInside:newP withEvent:event]) {returnself.centerBtn; } }return[superhitTest:point withEvent:event];}
触摸事件的传递是从父控件传递到子控件
响应是相反的
1.NSThread 2.GCD 3.NSOPeration
第一种很少人会用 他是oc开线程的方法 因为有许多缺点 所以很少人会用(缺点:手动管理线程, 无法利用多核技术) 第二种 第三种 需要掌握 这里我们主要说说GCD 是如何开线程的 第三种NSOPeration 是对苹果公司 对GCD 的一个封装(掌握)
队列是一个存放任务的容器,而线程是执行这些任务的东西
一类是表示原子性(也就是线程安全)的,有atomic和nonatomic,默认是atomic,acomic也就是线程安全,但是我们一般都用的nonatomic,因为atomic的线程安全开销太大,影响性能,即使需要保证线程安全,我们也可以通过自己的代码控制,而不用atomic。
一类是表示引用计数的,有assign(iOS5以前用unsafe_unretained),strong,weak,copy。
assign: assign用于非指针变量,一般用于基础类型和C数据类型,这些类型不是对象,统一由系统栈进行内存管理。 weak:对对象的弱引用,不增加对象的引用计数,也不持有对象,当对象消失后指针自动指向nil,所以这里也就防止了野指针的存在。
strong:对对象的强引用,会增加对象的引用计数,如果指向了一个空对象,会造成野指针,平常我们用得最多的应该也是strong了。
copy:建立一个引用计数为1的新对象,赋值时对传入值进行一份拷贝,所以使用copy关键字的时候,你将一个对象复制给该属性,该属性并不会持有那个对象,而是会创建一个新对象,并将那个对象的值拷贝给它。而使用copy关键字的对象必须要实现NSCopying协议。
unsafe_unretained:跟 weak 类似,声明一个弱引用,但是当引用计数为 0 时,变量不会自动设置为 nil,现在基本都用weak了。 一类是表示读写权限的,默认是readwrite(可读可写),还有就是readonly,当你希望暴露出来的属性不能被外界修改时就需要申明为readonly。
在这里要重点说一下,使用NSMutableArray,NSMutableDictionary等可变集合对象的时候千万不要用copy,这里用copy 99%会出错,因为当你给该属性赋值时它会自动调用对象的copy方法,从而将可变集合转换成不可变集合,把一个不可变集合赋值给一个可变集合,就会造成错误。
/* 1.weak 1>OC对象2.assign 1>基本数据类型 2>OC对象3.strong 1>OC对象4.copy 1> NSString 2> block5.使用weak和assign修饰OC对象的区别 1>成员变量1) weak生成的成员变量是用__weak修饰的,比如Cat * __weak _cat; 2) assign生成的成员变量是用__unsafe_unretained修饰的Cat * __unsafe_unretained _cat; 2>__weak和__unsafe_unretained1)都不是强指针(不是强引用),不能保住对象的命2) __weak :所指向的对象销毁后,会自动变成nil指针(空指针),不再指向已经销毁的对象3) __unsafe_unretained :所指向的对象销毁后,仍旧指向已经销毁的对象*/---------------------
这样看来,在不可变对象之间进行转换,strong与copy作用是一样的,但是如果在不可变与可变之间进行操作,那么比较推荐copy,这也就是为什么很多地方用copy,而不是strong修饰NSString,NSArray等存在可变不可变之分的类对象了,避免出现意外的数据操作.
Runtime 维护了一个 Weak 表,用于存储所有 Weak 指针。Weak 表是一个哈希表,Key 是对象的地址,Value 是一个数组,数组里面放的是 Weak 指针的地址(这个地址的值是所指对象的地址)。
简单来说,这个方法首先根据对象地址获取所有 Weak 指针地址的数组,然后遍历这个数组,把每个地址存储的数据设为 nil ,最后把这个 key-value entry 从 Weak 表中删除。
layoutIfNeeded和setNeedsLayout的区别
更新布局总会重新触发UIView的layoutSubviews方法。
layoutIfNeeded不一定会调用layoutSubviews方法。
setNeedsLayout一定会调用layoutSubviews方法(有延迟,在下一轮runloop结束前)。
你应该使用pod update PODNAME去只更新某个特定的库(检查是否有新版本,并尽可能更新到新的版本)。对应的,你应该使用pod install,这个命令不会更新那些已经安装了的库。
当你在你的Podfile里面添加了一个库的时候,你应该使用pod install,而不是pod update,这样既安装了这个库,也不需要去更新其它的已安装库。
你应该使用pod update去更新某个特定的库,或者所有的库(在Podfile的限制中)。
在OC中,==操作符对于对象类型只是比较对象地址,因为他和java一样不支持运算符重载,可以通过重写对象的isEqual方法来判断。
hash方法只在对象被添加至NSSet和设置为NSDictionary的key时会调用
hash方法主要是用于在Hash Table查询成员用的, 那么和我们要讨论的isEqual()有什么关系呢?
为了优化判等的效率, 基于hash的NSSet和NSDictionary在判断成员是否相等时, 会这样做
Step 1: 集成成员的hash值是否和目标hash值相等, 如果相同进入Step 2, 如果不等, 直接判断不相等
Step 2: hash值相同(即Step 1)的情况下, 再进行对象判等, 作为判等的结果
简单地说就是
hash值是对象判等的必要非充分条件
atomic 为什么不是线程安全的
变量的声明有两种情况:
1、一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。 告诉编译器,这个名字已经匹配到一块内存上,
2、另一种是不需要建立存储空间的。 例如:extern int a 其中变量a是在别的文件中定义的。
用static来声明一个变量的作用有二:
(1)对于局部变量用static声明,则是为该变量分配的空间在整个程序的执行期内都始终存在。
(2)外部变量用static来声明,则该变量的作用只限于本文件模块。
定义和声明的最重要区别就是:
定义创建对象并为这个对象分配了内存,声明没有分配内存。
+load 首先,load方法是一定会在runtime中被调用的,只要类被添加到runtime中了,就会调用load方法,所以我们可以自己实现laod方法来在这个时候执行一些行为。
而且有意思的一点是,load方法不会覆盖。也就是说,如果子类实现了load方法,那么会先调用父类的load方法,然后又去执行子类的load方法。同样的,如果分类实现了load方法,也会先执行主类的load方法,然后又会去执行分类的load方法。所以父类的load会执行很多次,这一点需要注意。而且执行顺序是 类 -> 子类 ->分类。而不同类之间的顺序不一定。
+initialize 与load不同的是,initialize方法不一定会执行。只有当一个类第一次被发送消息的时候会执行,注意是第一次。什么叫发送消息呢,就是执行类的一些方法的时候。也就是说这个方法是懒加载,没有用到这个类就不会调用,可以节省系统资源。
还有一点截然相反,却更符合我们预期的就是,initialize方法会覆盖。也就是说如果子类实现了initialize方法,就不会执行父类的了,直接执行子类本身的。如果分类实现了initialize方法,也不会再执行主类的。所以initialize方法的执行覆盖顺序是 分类 -> 子类 ->类。且只会有一个initialize方法被执行
是有效的只是在运行时不会有任何作用:
而给一个已经销毁的对象就会崩溃,因为 已经释放的对象,首先其内存可能已经被回收并且重新使用,这种情况下,你向其发送消息,实际上是给另外一个对象发送消息
网友评论