1、关于AES(以AES128为例)加密的CBC模式:
秘钥长度:
128位(16字节)
偏移量:
在CBC分组模式下每个明文块要先与前一个密文块进行异或后再加密,每个密文块都依赖于前面的所有明文块。
那么第一个明文快就要用到偏移量IV了。在CBC中,IV先与第一个明文块进行异或,得到第一个明文块。
填充模式:PKCS5/PKCS7
- PKCS5Padding限制了填充的Block Size为8字节(Bytes),填充块最多只能填充8个字节(Bytes),限定了范围,填充内容0x01-0x08;
- 当际上当分组块大于8字节时,如AES128是16字节时,理论上数据块分组需要补位的字节数:1-16个字节(Bytes),在AES加密当中严格来说是不能使用PKCS5的,因为AES的块大小是16字节(Bytes)而PKCS5只能用于8字节(Bytes),补不齐;
- 但是,通常我们在AES加密中所说的PKCS5指的就是PKCS7,在iOS中提供了PKCS7Padding,而Java中则提供了PKCS5Padding,而Java实际上当分组块大于8字节(Bytes)时,其PKCS5Padding与PKCS7Padding是相等的:每需要填充n个字节,每个字节填充的值是n (n的范围实际上就是PKCS7Padding的1-255字节数的范围)。
2、关于导航栏透明备忘录:
iOS7之后由于navigationBar.translucent默认是YES,坐标默认在(0,0)点 ,当不透明的时候(设为NO),零点坐标在(0,64); ps:64或88
1、如果你想设成透明的,而且还要零点从(0,64)开始,那就添加:
self.edgesForExtendedLayout = UIRectEdgeNone;
2、如果你想设成不透明的,而且还要坐标从(0,0)开始,添加
self.extendedLayoutIncludesOpaqueBars = YES;
3、关于响应链的备忘录:
1、如果第一响应者是自定义的UIControl的子类同时响应链上也绑定了手势识别器UIGestureRecognizer:
UIWindow会将事件先发送给响应链上绑定的手势识别器UIGestureRecognizer,再发送给第一响应者,如果手势识别器能成功识别事件,UIApplication默认会向第一响应者发送cancel响应事件的命令;如果手势识别器未能识别手势,而此时触摸并未结束,则停止向手势识别器发送事件,仅向第一响应者发送事件。如果手势识别器未能识别手势,且此时触摸已经结束,则向第一响应者发送end状态的touch事件,以停止对事件的响应。
2、如果第一响应者是UIControl的子类且是系统类(UIButton、UISwitch)同时响应链上也绑定了手势识别器UIGestureRecognizer:
UIWindow会将事件先发送给响应链上绑定的手势识别器UIGestureRecognizer,再发送给第一响应者,如果第一响应者能响应事件,UIControl调用调用sendAction:to:forEvent:将target、action以及event对象发送给UIApplication,UIApplication对象再通过 sendAction:to:from:forEvent:向target发送action。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
BOOL shouldInterceptTouches = YES;
CGPoint location = [self.view convertPoint:point fromView:self.targview];
CGRect rect = [self.view convertRect:self.targview.frame toView: self.view];
shouldInterceptTouches = CGRectContainsPoint(rect, location);
if (shouldInterceptTouches) {
return self.targview;
}else {
return self.view //// [super hitTest:point withEvent:event];
}
}
总结:UIControl的子类且是系统类UIButton,可以收到UIGestureRecognizer的透传响应,
自定义的UIControl会被手势响应拦截。
4、对大佬们<年终总结>的总结
https://onevcat.com/2021/01/2020-final/
https://blog.yuusann.com/corpus/article/21001
http://weibointl.api.weibo.com/share/194006618.html?weibo_id=4589331102307217
https://mp.weixin.qq.com/s/RLPsrxiD2ILbhLU6drvaYQ
http://blog.cnbang.net/living/3716/
https://www.roczhang.com/year-in-review-2020.html
5、oc 中 static 小tips
局部变量
1.只会被初始化一次,也就是只有一份内存。
2.生命周期被改变,一直到程序结束才释放
- (NSMapTable *)testMap{
static NSMapTable *map = nil;
if (!map) {
map = [NSMapTable mapTableWithKeyOptions:NSMapTableCopyIn valueOptions:NSMapTableWeakMemory];
}
return map;
}
如上的写法是,map只会初始一次
其他资料关于static说明:https://www.jianshu.com/p/4bfd96c57a6d
6、Hook方法交换中一个常见问题
为什么很多hook交换方法看着像递归,无限循环调用?比如(此处转用了其他作者文章代码):
+ (void)sjt_exchangeSelector:(SEL)oldSel andNewSelector:(SEL)newSel {
Method oldMethod = class_getInstanceMethod([self class], oldSel);
Method newMethod = class_getInstanceMethod([self class], newSel);
// 改变两个方法的具体指针指向
method_exchangeImplementations(oldMethod, newMethod);
}
+ (void)load {
// 该方法会在加载这个类的时候执行(APP启动时会加载,只执行一次)
// 此处交换descriptionWithLocale:与自己写的my_descriptionWithLocale:的方法指针
[self sjt_exchangeSelector:@selector(descriptionWithLocale:) andNewSelector:@selector(my_descriptionWithLocale:)];
}
- (NSString *)my_descriptionWithLocale:(id)locale {
NSString *desc = [self my_descriptionWithLocale:locale];
desc = [self replaceUnicode:desc];
return desc;
}
- (NSString *)replaceUnicode:(NSString *)unicodeStr {
NSString *tempStr1 = [unicodeStr stringByReplacingOccurrencesOfString:@"\\u" withString:@"\\U"];
NSString *tempStr2 = [tempStr1 stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
NSString *tempStr3 = [[@"\"" stringByAppendingString:tempStr2] stringByAppendingString:@"\""];
NSData *tempData = [tempStr3 dataUsingEncoding:NSUTF8StringEncoding];
NSString* returnStr = [NSPropertyListSerialization propertyListFromData:tempData
mutabilityOption:NSPropertyListImmutable
format:NULL
errorDescription:NULL];
return [returnStr stringByReplacingOccurrencesOfString:@"\\r\\n" withString:@"\n"];
}
问题:你好,我想知道为什么不会造成死循环,请问是否可以解答一下?
回答:先要弄清楚selector、IMP、Method三者之间的关系,通俗的方法Method是个结构体。method_exchangeImplementations交换的是这个这个两个方法的IMP。你代码中看到的是[self my_descriptionWithLocale:locale],实际上执行指向了[self descriptionWithLocale:locale]实现地址的指针,执行的是descriptionWithLocale内部实现。
7、 iOS 13获取keyWindow
@property(nullable, nonatomic,readonly) UIWindow *keyWindow
API_DEPRECATED("Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes", ios(2.0, 13.0));
- (UIWindow *)getKeyWindow
{
if (@available(iOS 13.0, *))
{
for (UIWindowScene* windowScene in [UIApplication sharedApplication].connectedScenes) {
if (windowScene.activationState == UISceneActivationStateForegroundActive)
{
for (UIWindow *window in windowScene.windows)
{
if (window.isKeyWindow)
{
return window;
break;
}
}
}
}
}
else
{
return [UIApplication sharedApplication].keyWindow;
}
return nil;
}
8、大白话讲TCP 为什么需要三次握手四次挥手:
1、TCP连接为什么是3次握手,不是1次、不是2次,也不是4次5次?
TCP建立有效连接的目的就是保证双方都具备两点能力:发送数据和接收数据。
生活场景:小明手机接通小王手机:
(第一次握手)小明:你好我是小明,你是小王吗?听得见我说话吗?
(第二次握手)小王:你好小明,我是小王,我可以听见你说话,你可以听见我说话吗?
(第三次握手)小明:我可以听见你说话。
日常生活中,如果说是把上面三次对话作为调试验证双方手机听筒(收数据能力)、话筒(发送数据能力)是否正常,这上面三句对话一句也不能少。
1)、如果小明说完上述第一句,也就是第一次握手就建立连接,就开始讲事情,碰到小王话筒小听坏了,小明就白讲了,没有意义的,所以1次握手不行。
2)、如果小王回复了上述第二句,也就是第二次握手就建立连接,这个时候小王的话筒是坏的(不能发送数据),这个时候小王开始讲事情也是白讲,因为小明根本听不到小王说话。
3)、只有小明回复小王上述第三句,也就是第三次握手之后建立连接,这个时候,就确认了双方的手机听筒(收数据能力)、话筒(发送数据能力)都正常,可以正常通话了。
所以、根据这个常识,只有三次才才可以,4次、5次都是多余,三次不能少,也不必多。
2、TCP连接为什么断开连接需要4次挥手?
这里讨论的TCP断开场景是:它已经建立了连接,现在传输数据的过程中。TCP是保证可靠传输的协议。
生活场景:小明和小王通话中,他们正在聊很重要的事情:
(第一次挥手)小明:你好小王,我有事情得挂断了!
(第二次挥手)小王:收到,那你稍等一会,等我把最后这重要的事说下你再挂断!
(第三次挥手)小王:你好小明,事情已经说完了,你可以挂断了!
(第四次挥手)小明:都已收到,我马上准备挂断。
为了把重要的事情说完(TCP为了保证正在传输的数据可靠性),小王多说了一句话,把重要的事情收尾了(把正在传输的数据传输完成)。这就是从生活白话场景中可以看到断开需要4次挥手。
另外:
1、其他的ACK、seq、FIN 等概念,都是基于这个基础原理设计的流程控制概念,具体可以参考:
大白话告诉你 TCP 为什么需要三次握手四次挥手
2、另外关于TCP粘包、分包问题,为什么UDP和IP包没有这样的问题,如何解决请参考:
TCP为什么会粘包?
3、TCP等参考资料链接
9、UIApplicationDelegate方法调用顺序(iOS 12)
传送门:UIApplicationDelegate方法调用顺序(iOS 12)