ios 编译时和运行时,求助iphone的应用编译运行错误

1,求助iphone的应用编译运行错误回复 yuanyuanliu 的帖子这个不好说,我们一般是使用gcc4.2那个编译器.具体的还应该看下具体的提示信息.这是个编译器的问题 。应该使用iOS支持的GCC和MAC支持的LLVM 。
2,iOS 运行时中方法的调用流程 在iOS运行时系统中,调用方法的本质就是利用objc_msgSend进行消息发送:iOS 中所有的类都是继承于 NSObject , 一个对象所具有的方法分为实例方法和类方法,编译完成后的对象中,存在一个实例方法链表、一个缓存方法链表 。当实例调用方法经objc_msgSend时:首先 , 在相应操做的对象中的缓存方法列表中找调用的方法,若找到,转向相应的实现并执行;若没找到,在对象的方法列表中查找 , 若是找到,转向相应的实现并执行;若是没找到,则递归的去父类指针所指向的类对象方法列表中查找;以此类推,若是一直到根类都没有找到,转向拦截调用,走消息转发机制;若是没有重写拦截调用方法,程序报错;消息转发也被称为拦截调用,就是在找不到调用的方法后,且在程序崩溃以前,有机会经过重写NSObject的四个方法来补救处理:若以上都不中,调用 NSObject 的 doesNotRecognizeSelector 方法抛出异常:利用以上机制,可以对resolveInstanceMethod 和 resolveClassMethod 两个方法进行方法交换,拦截可能出现的 iOS 崩溃,然后自定义处理 。消息转发机制依次的三个过程:1)动态方法解析;2)转发给其他备用的接收对象;3)消息所有相关内容封装成一个NSInvocation对象 , 再做最后的尝试 。第一阶段,先征询接收者所属的类,是否需要动态的添加方法,用来处理当前未找到的方法 。对象在无法解读消息时会首先调用所属类的下列类方法,来判断是否能接收消息:例:第二阶段,如果动态方法解析没有发现添加的方法,那么尝试转发给其他对象来处理这个方法 。该步骤调用的方法是:例:第三阶段,如果没有可用的备选者,那么系统就会把消息所有相关内容封装成一个NSInvocation对象,再做最后的尝试,启动完整的消息转发 。先调用methodSignatureForSelector:获取方法签名,然后再调用forwardInvocation:进行处理,这一步的处理可以直接转发给其它对象 , 即和第二步的效果等效 , 但是很少有人这么干,因为消息处理越靠后,就表示处理消息的成本越大,性能的开销就越大 。所以,在这种方式下,一般会改变消息内容,比如增加参数,改变选择子等等,具体根据实际情况而定 。例:这里就是利用了消息转发机制的第三个阶段,将NSIvocation分发给多个代理去响应 。https://blog.csdn.net/kingjxust/article/details/49559091http://blog.cnbang.net/tech/2808/http://blog.cnbang.net/tech/2855/由于OC的动态特性,在编译过程向类发送了其无法理解的消息并不会报错 , 因为在运行时 , 我们可以改变对象调用的方法、向类中添加方法 。只有当程序运行起来之后,才知道要真正执行哪个函数(动态绑定) 。OC消息发送原理、方法查找过程:简单理解:OC、运行时初始化时机:https://www.jianshu.com/p/4b93b40977b5https://blog.csdn.net/weixin_30920513/article/details/100093380参考文章:https://www.jianshu.com/p/7e132cda35cdhttps://www.cnblogs.com/feng9exe/p/10397102.htmlhttps://www.shangmayuan.com/a/02d9b8b219b24d888ef93b97.htmlhttps://blog.csdn.net/lin1109221208/article/details/108724965iOS之使用NSInvocation调用方法https://www.jianshu.com/p/e24b3420f1b4
3,simulator模拟器怎么用Xcode编译iOS项目后自动打开iOS模拟器(去调试当前程序),在调试Xcode中的iOS程序时,点击对应的Run;Xcode会去编译当前iOS项目,编译成功后,会自动并调用iOS模拟器,并运行相应的编译出来的程序;注:你当前的项目,所使用的对应模拟器需要设置为对应的模拟器,比如我此处的项目是针对iPhone的,所以设置为iPhone 5.1 Simulator;如有需要,当然也可以手动自己去打开对应的iOS模拟器 。【ios 编译时和运行时,求助iphone的应用编译运行错误】
4 , iOS Runtime理解 runtime概述: runtime又叫运行时 , 是一套底层C语言API,是iOS系统的核心之一 。开发者在编码过程中,可以给任意一个对象发送消息,在编译阶段只是确定了要向接受着发送这条消息 , 而接受者如何响应和处理这条消息,就要看运行时来决定了C语言中 , 在编译器就确定要调用哪个函数,而OC的函数,属于动态调用过程,在编译器并不能真正决定调用哪个函数,只有在真正的运行时才会根据函数的名称找到对应的函数来调用 。OC是一个动态语言,这意味着它不仅要一个编译器,也需要一个运行时系统来动态创建类和对象、进行消息传递和发送1.消息转发Runtime的特性主要是消息传递,如果消息在对象中找不到,就进行转发 。Objective-C是一个动态语言 , 这意味着它不仅需要一个编译器,也需要一个运行时系统来动态创建类和对象、进行消息传递和转发 。Runtime的核心是消息传递 。(1)消息传递的过程一个对象的方法[obj test],编译器转成消息发送objc_msgSend(obj,test),Runtime执行的流程是这样的a.首先通过obj的isa指针找到它的classb.在class的method list找testc.如果class中没找到test,继续往它的superclass中找d.一旦找到test这个函数,就去执行它的IMP由于效率问题,每个消息都遍历一次objc_method_list并不合理,所以需要把经常被调用的函数缓存下来,去提高函数查询的效率 。这也就是objc_class中另一个重要的成员objc_cache做的事情 。找到test之后 , 将test的method_name作为key,method_imp作为value 。当再次收到test消息的时候,可以直接在cache里找 。类对象(objc_class)Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针 。struct objc_class结构体里面定义了很多变量 。结构体里保存了指向父类的指针、类的名字(name)、版本、实例变量列表(ivars)、方法列表(methodLists)、缓存(cache)、遵守的协议列表(protocols),由此可见 , 类对象就是一个结构体struct objc_class,这个结构体存放的数据就是元数据理解Runtime就是理解iOS在运行时他的数据存储以及他的类、实例、类对象、元类她们之间的关系和作用 。(2)消息转发机制归根到底 , Objective-C中所有的方法调用本质就是向对象发送消息1.类中创建方法-(void)test2.iOS系统为这个方法创建一个编号 , SEL(test)并添加到方法列表里面3.当调用这个方法的时候系统去方法列表里查找这个方法,找到了就执行所以,调用一个方法就会进行一次发送消息也就是在这个类的方法列表里找,如果在该类中找不到就到该类的父类里找,如果父类还找不到就一直搜索到继承树的根部,如果找不到或者消息转发不成功那就会报unrecognized selector错 。1.动态方法解析Objective-C运行时会调用+resolveInstanceMethod:或者 +resolveClassMethod:让你有机会提供一个函数实现,如果你添加了函数并且返回YES,那么运行时就会重新启动一次消息发送的过程 。如下图:虽然没有foo:的实现函数,但是通过class_addMethod()动态添加了fooMethod函数 , 并执行了这个函数并且打印成功 。如果reslove返回NO运行时就会移到下一步:forwardingTargetSelector2.直接消息转发如果目标对象实现了forwardingTargetSelector , Runtime这时就会调用这个方法 , 给你把这个消息转发给其他对象的机会从图中可以看出我们通过forwardingTargetForSelector方法将当前类的方法转给Father类实现了,打印成功 。3.完整消息转发如果在上一步还不能处理未知消息,那唯一能做的就是启动消息转发机制 。首先它会发送methodSignatureForSelector消息获得函数的参数和返回值类型 。如果methodSignatureForSelector返回nil,Runtime则会发出doesNotRecognizeSelector 。如果返回一个签名函数,Runtime就会创建一个NSInvocation对象并发送forwardInvocation消息给目标对象 。Runtime的实际应用1.使用Runtime交换方法2.动态添加方法(目前不是很懂)3.给分类添加属性4.消息转发(热更新)解决Bug(JSPatch)5,Unity3D开发中热更新为什么不能使用C的思考阅读了网上一些文章,其实使用C#进行热更新是可以的,将需要更新的代码打包成程序集,然后利用反射即可 , 但是也提到在IOS平台是不行的,至于为什么不行,就不再说了 , 然后就是推荐Lua作为热更新方案,但是,为啥Lua就行?C#就不行?因为C#是编译型语言,Lua是解释型语言?好多人都说Lua能热更新,是因为它是解释型语言,不用编译,在运行时能动态解释Lua代码并运行 。这种方法实际上不准确 , 从某些角度来说是错的 。Lua确实是解释性脚本语言,但是不是因为是解释型才能进行热更新 。即使使用C++这种编译语言,也能进行热更新,将动态链接库进行更新就是,然后动态加载动态链接库获取更新的函数地址即可 。而且,还有一点,C#并不能说是一种编译型语言,C#代码会被编译成IL,IL解释成机器码的过程可以在运行之前进行也能在运行时进行 。如果在运行时进行解释 , 那么和Lua不就一样了吗,为啥C#不能进行热更新呢?JIT对IL进行解释执行的原理首先说一下,JIT对IL如何在运行时进行解释并执行的,大致过程为:将IL解释为所在平台的机器码,开辟一段内存空间,要求这段内存空间可读、可写、可执行,然后把解释出的机器码放入,修改CPU中的指令指针寄存器中的地址 , 让CPU执行之前解释出来的机器码 。注意这段内存的条件 , 最重要的一条是必须是可执行的,一般的内存申请我们只是存放数据 , 但是这里的内存权限要是有可执行权限IOS限制了什么?IOS不允许获取具有可执行权限的内存空间,这就直接要求JIT要以full AOT模式,这种模式会在生成之前把IL直接翻译成机器码而不是在运行期间,进行了这种操作C#从某种角度来说和C++一样,成为了编译型语言,失去了运行时解释的功能 。Lua的解释执行怎么就行呢?如果Lua的解释执行原理和C#相同,肯定也不能在IOS平台上运行时解释执行 。Lua是使用C编写的脚本语言,它在运行时读入Lua编写的代码,在解释Lua字节码(Lua自己的指令)时不是翻译为机器码,而是使用C代码进行解释,不用开辟特殊的内存空间,也不会有新代码在执行 , 执行的是Lua的虚拟机,用C写出来的虚拟机,这和C#的机制是完全不同的 , 因为Lua是基于C的脚本语言 。总结说白了 , 就是由于Lua这种脚本语言的特性 , 基于已经存在的某种语言的一种新的语言,这也是脚本语言和C#、C++这类语言的本质区别 。当然,Lua虚拟机不仅可以使用C写,也可以用C#写 。使用热更新也不一定非要用Lua,Python同样可以,只不过Lua短小精悍,本身代码长度就不是很大,可以从GitHub上看到 。最新版的unity取消那个js脚本了,也就是unityscript 。。未来将仅支持c#原本那个js语法的存在 , 是为了让没接触过静态语言的新手过度用的,但后来官方发现全球只有3.6%的用户使用了这门语言 。。而且其中有一部分还是unity官方的开发人员 。。因此这门语言的使用人数,几乎可以忽略不计 。。而且这门语言的存在,又会降低unity的性能 。。因此老版本的unity,为了保留这门语言,在性能方面长期存在缺陷 。。比如lambda可能引发内存泄漏等问题 。。去年unity官方就有过一个投票活动,投票内容是“是否应该取消unityscript而使unity获得更好的性能?”,两个月前,又发布了一个要取消unityscript的公告 , 现在果然就把unityscript取消了 。如果你是unity老用户,对这个结果应该不会感到任何奇怪 。对于绝大多数开发者来说 , 那个unityscript确实是多余的 。附上官方微博的公告6,为什么苹果打开应用的速度那么快而安卓比较慢呢总的来说有四个原因吧 。1. 系统环境不同 。苹果使用的是iOS系统,它只要保证那几款iPhone的硬件设备能够顺畅运行就OK了 , 可控性方面是安卓机子没法比的;而安卓机子搭载的是谷歌的Android系统,它不仅要保证现有的硬件能够顺畅运行,还要确保以后未知的不同硬件组合,可控环境就逊色了很多 。2. 优先级别不同 。我们拿iPhone和安卓手机同样滑屏解锁 , e799bee5baa6e79fa5e98193e58685e5aeb931333337613166点击相同的应用程序打开 , 苹果往往会变现得比较顺畅一些 , 而有的安卓机子就会显得有些卡顿,这个其实就是iOS最先相应屏幕的原因所在 。iOS对屏幕的相应顺序是:触摸Touch→媒体Media→服务Service→架构Core,而Android系统的响应顺序是:程序Application→框架Framework→屏幕显示资源Library→架构Kernal 。3. 开发机制不同 。iOS采用Objective-C语言,Android采用的是Java,前者效率高,后者运行效率偏低,这就造成了各自系统之间的流畅度的不同 。4. 后台运行不同 。iOS的后台程序并不像Android一样在后台一直运行,我们在iOS后台所看到的运行程序 , 其实只是我们最近的使用记录,就跟网页浏览记录一样;而Android后台运行程序如果没手动关闭退出 , 它们就会一直在后台中运行,这样系统就需要更多的运行内存来给这些应用程序 。所以 , 这也是直接导致iOS只需要双核1GB运行内存就可以保持很顺畅了,而Android却要达到4GB内存 , 八核的CPU处理器 。感觉最根本的原因 两个系统的代码环境不一样 ios的c直译为可识别二进制文件 而安卓由java开发 java运行需要跑个虚拟机进行转译 这是不可逆的 觉得主要就是多了虚拟机这步我android的也很快,现在android也做的很好了1.iOS设备硬件高端,iOS家族里面没有低端设备,而Android家族则有不少低端设备;Android的高端机器也不是如主流观点一样都是硬件性能逆天的,比如之前很多Android旗舰用的Tegra 3处理器就存在内存带宽小而影响性能发挥的问题 , 高通的Adreno系列GPU的实际性能也不算特别好;反观iOS机器,比如ipad 4的PowerVR SGX 544MP4 , iphone 5的PowerVR SGX 543MP3,都是移动GPU里的高端型号 , 更有高内存带宽支持,性能很好;至于CPU , 虽然Android家族已经很多四核机器了,iOS家族基本还是双核 , 但是核心数量和性能没必然的关系,你能说红米的MTK四核CPU比你电脑的英特尔双核CPU还强吗?iOS设备的CPU性能也属于优秀水平 。2.Android的应用大部分都是用Java语言开发 , 编译成一种“中间代码”,在Dalvik VM虚拟机上运行 , 程序运行时还要通过虚拟机对“中间代码”进行编译才能运行,运行效率不高,更耗费硬件资源,只有少部分应用,比如游戏之类的 , 要求性能的,会使用Android NDK进行C/C++开发 , 不过也不能算纯粹的Native程序;而iOS的应用使用Object-C语言进行开发,编译成可直接运行的二进制代码 , 都是Native程序,运行效率高 , 消耗资源更?。徊渭庸惴ň喝娜硕贾? ,Java在时间和空间方面的要求都会比C/C++宽松一倍,就因为Java程序运行效率较低;同时,Android的程序有着更为自由的后台运行能力,相比iOS的多任务机制,Android的多任务要消耗多一点的硬件资源 。3.苹果拥有多年的操作系统研发经验,在iOS上采用了很多优化和设计来实现流畅的运行,比如使用GPU绘制界面,高帧数的动画,高优先e799bee5baa6e997aee7ad94e59b9ee7ad9431333335313131级的界面渲染和触摸响应等等 , 流畅并不等于速度快,iOS的运行速度很多时候其实并不快 , 只是用了高帧数的过渡动画,使你感觉这是一个连续的过程,不至于有断续感 , 从而感觉到运行很快,其实功能机的运行速度也很快,但就是缺少了过渡动画 , 没有给人那种连贯的感觉,比如打开存有大量短信的短信程序,功能机耗时是1s , iOS耗时1.5s,理论上功能机快 , 但iOS的过渡动画让人觉得速度更快;而Android早期一直是谷歌的移动广告平台的定位,直到Android 4.0发布之后 , 才可以说是成为谷歌重点支持的移动操作系统,所以,Android 4.0之后的Android版本在各方面才有了巨大提升,Android很多对性能有极大帮助的特性都是Android 3.0时才出现的,Android系统底层所做的优化相对不足,比如Android 3.0以下的版本都无法使用GPU绘制界面 , 即使Android 4.x,也要打开“强制GPU渲染”才能在全局使用GPU绘制界面,还有界面渲染框架的效率不高等问题 。4.使用智能手机更多是在使用各种应用 , 苹果iOS平台的应用生态环境相比谷歌Android平台要好很多,精品应用为数众多 , 这些精品应用质量都很高,运行流畅、速度快、用户体验好 , 这些都要归功于苹果App Store严格的审核制度和优秀的盈利模式;Google Play Store在Android 4.0发布之后发展也很快,但是宽松的审核制度,Android平台开放的环境导致盗版横行,开发者,尤其个人开发者热情不高 , 很多应用质量很差,其中也不乏大公司的产品,连最基本符合Android Design都做不到,完全照搬iOS的界面 , 其质量可想而已,这些也严重拉低了Android的用户体验水平 。系统不一样被 。

    推荐阅读