当前位置: 首页 > 科技观察

再来说说京东的七大美食,总结

时间:2023-03-13 15:04:13 科技观察

文章结束本文转载自微信公众号“Swift社区”,作者朱普瑞。转载本文请联系Swift社区公众号。1、http链接断开的过程?第一步:TCP建立连接:三次握手HTTP是一个应用层协议,它的工作也需要数据层协议的支持。TCP协议(应用层,数据层在OSI七层模型中,后面会提到)。TCP协议被称为数据传输协议,它是可靠的、面向连接的、面向字节的。面向连接:通信前先建立连接,保证双方在线。可靠传输:网络正常时,数据不会丢失。面向字节流:传输灵活,但TCP传输存在粘包问题,没有明显的数据约定。在正式发送请求之前,需要建立TCP连接。建立TCP连接的过程简单来说就是在客户端和服务器之间发送三个消息来保证连接的建立。这个过程称为三次握手。第二步:浏览器发送请求命令。TCP连接建立后,客户端可以向服务器发送请求报文进行请求。请求报文分为请求行、请求头、空行、请求体。行和请求头中的内容获取客户端的信息,请求体中的数据获取客户端传递过来的数据。Step3:Response收到客户端的请求报文并确认后。服务器将向客户端发送响应消息。响应消息由状态行、响应头、空行和响应主体组成。服务器通过状态行和响应头告诉客户端请求的状态以及如何处理数据。真正的数据在响应体中传输给客户端。第四步:断开TCP连接。当请求完成后,需要断开TCP连接。断线过程。简单的说就是客户端和服务端发送4条消息来保证连接断开。故称四浪。扩展:1、单向请求HTTP请求是单向的,是一种只能由客户端请求,服务器端响应的请求-响应模式。(如果需要双向请求,可以使用socket)2、基于TCP协议HTTP是一个应用层协议,所以它的数据传输部分是基于TCP协议实现的。3.StatelessHTTP请求是无状态的,即没有记忆功能,无法获取之前请求或响应的内容。一开始,这种简单的模式可以加快处理速度,保证协议的稳定性,但是随着应用的发展,这种无状态的模式会让我们的业务实现变得麻烦。例如,如果我们需要保存用户的登录状态,我们就必须使用数据库来实现。于是乎,为了维护状态,引入了Cookie技术来管理状态。4、无连接HTTP协议无法保存连接状态。每个连接只处理一个请求,用完就终止,以节省传输时间,提高并发性。TCP连接断开后,客户端和服务器就像陌生人一样,下次再发送请求时,又得重新建立连接。有时候,当我们需要频繁发送请求时,这种无连接状态会消耗更多的请求时间(因为建立和断开连接本身也需要时间),所以HTTP1.1提出了持久连接的概念,可以通过设置Connection:keep-alive来实现在请求标头中。2.深拷贝、浅拷贝深拷贝、浅拷贝实例说明?深拷贝:是对象本身的拷贝;浅拷贝:是指针的拷贝;在oc中,父类的指针可以指向子类的对象,这是多态的一个特点,就是声明一个NSString对象,让它指向一个NSMutableString对象。这是完全可以的,因为NSMutableString的父类是NSString。NSMutableString是一个可以改变的对象。如果我们用strong修饰,NSString对象强引用了NSMutableString对象。如果我们在别处修改这个NSMutableString对象,NSString的值也会随之改变。关于复制修改1.复制NSString->这是一个浅复制,但是因为是不可变对象,所以后面的值不会改变;2.MutableCopyNSString->这是一个深拷贝,但是拷贝的是一个可变对象NSMutableString;3.CopyNSMutableString->这是一个深拷贝,拷贝一个不可变对象;4.MutableCopyNSmutableString->这是一个深拷贝,拷贝一个可变对象Object;总结:Mutable复制一个对象,不管对象是可变的还是不可变的,都是深拷贝,复制的对象是可变的;复制对象,副本是不可变的。对于系统的非容器类对象,我们可以认为如果复制一个不可变对象,copy就是指针拷贝(浅拷贝),mutableCopy就是对象拷贝(深拷贝)。如果是可变对象的拷贝,就是深拷贝,但是拷贝返回的对象是不可变的。指的是NSArray、NSDictionary等。对于容器类本身,上面讨论的结论也是适用的,需要讨论的是复制后容器中对象的变化。//copy返回不可变对象,mutablecopy返回可变对象NSArray*array1=[NSArrayarrayWithObjects:@"a",@"b",@"c",nil];NSArray*arrayCopy1=[array1copy];//arrayCopy1是同一个NSArray对象作为数组(指向同一个对象),包括数组中的元素也指向同一个指针NSLog(@"array1retaincount:%d",[array1retainCount]);NSLog(@"array1retaincount:%d",[arrayCopy1retainCount]);NSMutableArray*mArrayCopy1=[array1mutableCopy];mArrayCopy1是array1的可变副本,指向的对象与array1不同,但其中的元素和array1中的元素指向同一个对象。mArrayCopy1也可以修改自己的对象[mArrayCopy1addObject:@"de"];[mArrayCopy1removeObjectAtIndex:0];array1和arrayCopy1是指针拷贝,mArrayCopy1是对象拷贝,mArrayCopy1也可以改变期间的元素:删除或添加。但注意容器中元素的内容是指针复制的。NSArray*mArray1=[NSArrayarrayWithObjects:[NSMutableStringstringWithString:@"a"],@"b",@"c",nil];NSArray*mArrayCopy2=[mArray1copy];NSMutableArray*mArrayMCopy1=[mArray1mutableCopy];NSMutableString*testString=[mArray1objectAtIndex:0];[testStringappendString:@"tail"];NSLog(@"%@-%@-%@",mArray1,mArrayMCopy1,mArrayCopy2);结果:mArray1,mArrayMCopy1,mArrayCopy2三个数组的第一个元素一切都发生了改变!3、load和initialize的区别load方法和initialize方法的区别,在子类、父类、类中的调用顺序?+(void)load1,+load方法加载顺序:父类>子类>类别(load方法会加载)注:(如果类别中有A,B,顺序取决于A,B的先后顺序添加到项目中),可能的结果:(父类>子类>类A>类B)或(父类>子类>类B>类A)2.+load方法不会被覆盖(例如,如果有父类、子类、类A、类B,这四种加载方法都会加载)。3、在主函数+(void)initialize1之前调用了+load方法。分类(子类没有initialize方法,父类存在或者没有1initialize方法)2.分类>子类(多个分类依赖编译顺序,只有一个存在)3.父类>子类(类没有initialize方法)4.父类(子类,类别没有initialize方法)总结+initialize:1.调用子类的+initialize方法时,先调用父类,如果父类有分类,则分类+initialize会覆盖父类2,分类+初始化会覆盖父类3,子类+初始化不会覆盖分类4,父类+初始化不一定会调用,因为有可能父类的分类覆盖它。5.发生在main函数之后。4、同名方法的调用顺序子类、父类、类中同名方法的调用顺序?load、initialize方法调用源码分析[1]注:+load方法是根据方法地址直接调用,不是通过objc_msgSend函数调用(通过isa和superclass寻找方法),所以不会有方法覆盖的问题.5.事件响应链事件响应链(同一个controller有3个view,如何判断它们是否有相同的父view)当iOS系统检测到手指触摸(Touch)操作时,会封装成一个UIEvent对象并放到它进入当前活动应用程序的事件队列。单例UIApplication会从事件队列中取出触摸事件,传递给单例UIWindow进行处理。UIWindow对象首先会使用hitTest:withEvent:方法找到Touch操作的初始点所在的view(View),也就是需要将touch事件传递给它处理的view。这个过程称为命中测试视图。UIAppliction-->UIWiondw-->递归寻找最适合处理事件的控件-->控件调用touches方法-->判断touches方法是否实现-->如果没有实现,则传递事件默认为上一个响应者-->FoundThepreviousresponder.UIResponder是所有响应对象的基类,UIResponder类中定义了处理上述各种事件的接口。大家熟悉的UIApplication、UIViewController、UIWindow以及所有继承自UIView的UIKit类,都是直接或间接继承自UIResponder,所以它们的实例都是响应者对象,可以组成响应者链。UIResponder*nextResponder=gView.nextResponder;NSMutableString*p=[NSMutableStringstringWithString:@"--"];while(nextResponder){NSLog(@"%@%@",p,NSStringFromClass([nextResponderclass]));[pappendString:@"--"];nextResponder=nextResponder.nextResponder;}如果有父视图,则nextResponder指向父视图。如果是控制器根视图,则指向控制器;如果控制器在导航控制器中,则指向导航控制器的相关显示。视图最终指向导航控制器;如果它是根控制器,它指向UIWindow;UIWindow的nexResponder指向UIApplication,最后指向AppDelegate。6、TCP丢包。TCP会丢包吗?如何处理?如果网络断开,会断开连接还是等待?TCP如果在不可靠的网络上实现可靠传输,必然会出现丢包的情况。包。TCP是一种“流”协议。一个特定的数据包会被TCP拆分成若干个数据包上传,小数据包会打包成大数据包上传。这就是TCPsticking和unpacking的问题。TCP丢包总结[2]7、自动释放池创建和释放时,子线程什么时候创建和释放?默认情况下,主线程的runloop是开启的,子线程的runloop(runloop)默认是不开启的,也就是说子线程中不会创建autoreleasepool,所以我们需要创建我们自己在子线程中的自动释放池。(子线程中使用的类方法都是autorelease,不会有pool释放,也就是后面没有办法释放,导致内存泄露。)如果主线程发生了事件,那么runloop将返回创建自动释放池。通过这个道理我们知道了为什么不会在子线程中创建autoreleasepool,因为子线程的runloop默认是关闭的,所以不会自动创建autoreleasepool,需要我们手动添加.如果生成子线程,线程一开始执行就创建自动释放池,否则会出现内存泄漏。因为子线程无法访问主线程的自动释放池。八、计算机编译过程源文件:加载.h、.m、.cpp等文件预处理:替换宏、删除注释、展开头文件、生成.i文件编译:将.i文件转换成汇编语言生成.i文件。s文件汇编:将汇编文件转换为机器码文件,并生成.o文件链接:参考.o文件中引用其他库的地方,生成最终的可执行文件dyld加载过程[3]作者:朱普瑞、林毅、怪物先生参考[1]加载、初始化方法调用源码分析:https://www.jianshu.com/p/e5c89e9045cf[2]TCP丢包总结:https://blog.csdn.net/weixin_41563161/article/details/105310459[3]dyld加载过程:https://www.jianshu.com/p/db765ff4e36a