iOS编程基础-OC(七)-运行时系统

2023-11-18

该系列文章系个人读书笔记及总结性内容,任何组织和个人不得转载进行商业活动!


 第7章 运行时系统

     

     终于到了运行时这一章,让我们来一步一步揭开它神秘的面纱吧;

     

     OC拥有相当多的动态特性,这些特性在运行程序时发挥作用,而不是在编译或链接代码时发挥作用;

     OC运行时系统实现了这些特性;这些功能也为OC语言提供了非常强大的功能和灵活性;

        开发人员使用它们能够以实时方式促进程序的开发和更新,而无需重新编译和部署;对软件影响也比较低;

     

     本章内容:

        了解OC运行时系统的工作方式;

        介绍OC语言的动态功能以及在程序中它们的使用方式;

     

     

     7.1 动态功能

     

     在运行时,OC语言会执行其他语言在程序编译或链接时会执行的许多常规操作,如确定类型和方法解析;

        这些操作还可以提供API,使你编写的程序能够执行额外的运行时操作;

        如对象内省和以动态方式创建和加载代码;

        OC运行时系统的结构和实现方式生成了这些动态特性;

     

     接下来介绍这些特性以及在开发程序时使用它们的方式;

     

     

     7.2 对象消息

     

     OOP术语;

     消息传递:指一种在对象之间发送和接收消息的通信方式;

        OC中,消息传递(如对象消息传递)用于调用类和实例(对象)的方法

        语法举例如下:

     接收器            消息

     [加法器   加数1:25 加数2:25]

                        ||

                        选择器

                    加数1:加数2

     

     分析:

        以加法器作为接收器,接收消息(即向加法器发送消息);

        在上边的这个消息传递表达式中,接收器(加法器)是消息的目的地(即对象或类);

        消息本身(加数1:25 加数2:25)则是由选择器和相应的输入参数构成;

     

     对象消息传递是以动态方式实现的特性;

        接收器的类型 和 相应的调用方法是在运行时决定的;

        示例如下:

        消息

     [接收器的performComputation方法]

         |

         ——>OC运行时系统:

                1)决定消息接收器的类型(决定的是动态类型,静态类型在声明时就已经决定)

                2)决定实现的方法(动态绑定:关键的是选择器 和 方法签名)

                3)调用方法;(调用接收器的方法-performComputation)

     

     上述过程描述了OC运行时系统通过动态类型和动态绑定,将消息与方法对应起来的方式;

        使用对象消息传递的动态编程特性可以获得极大的灵活性;

        可以简化接口,还可以在执行程序时,开发可修改或更新的模块化应用;

     

     因为OC程序是在运行时处理方法调用的,所以会存在与动态绑定有关的额外开销;

        OC运行时系统通过缓存的方法调用,节省用于向方法发送消息所消耗的内存,从而减少额外的开销;

     

     运行时系统处理方法调用的另一种方式是:

        接收器不保证一定会对消息做出回应;

        如果接收器没有消息做出回应,他就会抛出一个运行时异常;

        OC提供了多个用于处理这种情况的特性(如对象内省和消息转发);

     

     OC对象消息传递中具有下列关键元素:

     1)消息:向对象/类发送的名称(选择器)和一系列参数;

     2)方法:OC中的类或实例方法,其声明中含有名称、输入参数、返回值和方法签名(即输入参数和返回值的数据类型);

     3)方法绑定:接收向指定接收器发送的消息并寻找和执行适当方法的处理过程;

        OC运行时在调用方法时,会以动态绑定方式处理消息;

     

     接下来介绍选择器和方法签名(method signature);

     

     7.2.1 选择器

     

     选择器:在OC的对象消息传递中,选择器是一种字符串,用于指明调用对象或类中的哪个(些)方法;

            选择器是一种分为多个段的文本字符串,每个段以冒号结尾并且后跟参数;

            例如:分段1:分段2:分段3:

            这个选择器有3个分段,每个分段都带有一个冒号,因而表明相应的消息有三个输入参数;

            消息的参数与选择器的分段一一对应;

     

     OC运行时系统使用选择器,为目标对象/类提供正确的方法实现代码;

     在OC源代码中,消息的选择器直接与一个或多个类/实例方法声明对应;

     

     我们举一个例子:

        类A的实例a,定义接口-(int)addNum1:(NSInteger)n1 num2:(NSInteger)n2;

        A类实例方法的选择器为addNum1:num2:

        调用该实例方法需要使用接收器对象a后跟带输入参数的选择器:[a addNum1:1 num2:2];

     

     这个例子展示了选择器在对象消息传递中的作用;

     这些事物的运作方式为:

        当源代码被编译时,编译器(运行时系统的组成部分)会创建数据结构和函数调用语句,使用它们以动态方式将接收器(类/对象)和消息选择器与方法的实现代码对应起来;

        在执行程序时,运行时库(运行时系统的另一个组成部分)利用这些信息找到并调用适当的方法;

        稍后会介绍运行时系统的各个组成部分;

     

     1.空选择器分段:

        举个例子,有这样一个选择器 sumAddend1::

        在这个选择器中,第一个分段具有一个文本字符串,而第二个分段没有文本字符串;

        实际上,拥有一个以上分段的选择器都可以拥有 空选择器分段(即没有文本字符串的分段);

        空参数(空选择器分段)并不常见,因为出错时会难以对错误进行定位;

     

     2.SEL类型:

        我们已经知道在消息中使用文本字符串定义选择器的方式;接下来看看选择器的类型;

     

     选择器类型(SEL):是一种特殊的OC数据类型,是用于在编译源代码时替换选择器值的唯一标识符;

        所有具有相同选择器值的方法都拥有相同的SEL标识符;

        OC运行时系统会确保每一个选择器标识符的唯一性;

        可以使用关键字@selector创建SEL类型的变量

     如下示例:

-(NSNumber *)testSELTypeMethodAddNum1:(NSNumber *)a Num2:(NSNumber *)b{
    NSNumber * c = [NSNumber numberWithFloat: [a floatValue] + [b floatValue]];
    NSLog(@"a + b = %@",c);
    return c;
}

     

    SEL myMethod = @selector(testSELTypeMethodAddNum1:Num2:);
 

      之所以使用SEL类型是因为:

        OC运行时系统(在NSObject中)含有许多将SEL型变量用作参数的动态方法;

        除了获取对象和类的信息,NSObject类还有很多方法,它们用于使用选择器参数调用对象的方法;

      如下示例:


    [self performSelector:@selector(testSELTypeMethodAddNum1:Num2:) withObject:@1 withObject:@2];

     log:

     2017-11-28 10:33:51.926567+0800 精通Objective-C[641:12164711] a + b = 3


     这个NSObject的实例方法performSelector:withObject:withObject: ,调用了选择器变量指定的方法;

        其中的@selector指令会在编译时创建一个选择器变量;

        也可以使用Foundation框架中的NSSelectorFromString函数在运行时创建选择器;

        因此上述示例你也可以这样写:

     

    SEL addMethod = NSSelectorFromString(@"testSELTypeMethodAddNum1:Num2:");
    [self performSelector:addMethod withObject:@3 withObject:@2];


     log:

     2017-11-28 10:37:08.824019+0800 精通Objective-C[717:12171435] a + b = 5

     

     7.2.2 方法签名

     

     前面我们已经介绍了消息接收器、选择器和SEL类型,接下来介绍方法特征及其在对象消息传递中的作用;

     

     方法签名(method signature):

        定义了方法输入参数的数据类型和方法返回值(如果存在);

     

     在了解方法签名的作用之前,我们先来研究下运行时系统实现对象消息传递的方式;

     (第八章将详细介绍运行时系统和实现动态行为(如对象消息传递)的方式;本章着重介绍运行时系统的体系结构,而不是细节)

        编译器会将[接收器 消息]形式的对象消息,转换为声明中含有方法签名的(ANSI)C函数调用语句;

        因此,为了生成正确的对象消息传递代码,编译器需要获得选择器值和方法签名;

     

     编译器可以从对象消息表达式中轻松提取选择器;获取方法签名的过程则要麻烦些;

     

     获取方法签名:

        由于接收器(和相应的方法)是在程序运行时确定的,所以编译器无法知道使用怎样的数据类型才能与要调用的方法对应起来;

        为了获取方法签名,编译器会根据已解析的方法声明进行猜测;

        如果找不到方法签名,或者从声明获得的方法签名和运行时实际执行的方法匹配不上,就会出现方法签名不匹配的情况,从而导致从编译器警告到运行时错误的各种问题;

     

     7.2.3 使用对象消息

     进行一个选择器与SEL类型的练习;

     

     我们定义类C7Calculator可以计算整形加法;

        方法实现中使用了NSStringFromSelector(_cmd)获取被调用方法的选择器文本字符串;

        NSStringFromSelector函数需要一个SEL类型的变量;_cmd是一个隐式参数(即无需声明就存在于所有OC方法中的参数),它含有被发送信息中的选择器;

#import <Foundation/Foundation.h>

@interface C7Calculator : NSObject

-(NSNumber *)sumAddend1:(NSNumber *)adder1 addend2:(NSNumber *)adder2;
-(NSNumber *)sumAddend1:(NSNumber *)adder1 :(NSNumber *)adder2;//这个方法的第二个参数使用空参数

@end

#import "C7Calculator.h"

@implementation C7Calculator

-(NSNumber *)sumAddend1:(NSNumber *)adder1 addend2:(NSNumber *)adder2{
    NSLog(@"Invoking method on %@ object with selector %@",NSStringFromClass([self class]),NSStringFromSelector(_cmd));
    return [NSNumber numberWithInteger:([adder1 integerValue]+[adder2 integerValue])];
}
-(NSNumber *)sumAddend1:(NSNumber *)adder1 :(NSNumber *)adder2{//这个方法的第二个参数使用空参数
    NSLog(@"Invoking method on %@ object with selector %@",NSStringFromClass([self class]),NSStringFromSelector(_cmd));
    return [NSNumber numberWithInteger:([adder1 integerValue]+[adder2 integerValue])];
}

@end
     

     编码测试下: 

    C7Calculator * cal = [[C7Calculator alloc]init];
    [cal sumAddend1:@2 addend2:@3];

     log:

     2017-11-28 15:09:57.628257+0800 精通Objective-C[4697:12909535] Invoking method on C7Calculator object with selector sumAddend1:addend2:


     接下来编写调用对象中动态方法的代码;使用NSObject的performSelector:withObject:withObject:方法,该方法需要制定选择器和参数;

   [cal performSelector:@selector(sumAddend1:addend2:) withObject:@2 withObject:@5];
    [cal performSelector:NSSelectorFromString(@"sumAddend1::") withObject:@1 withObject:@3];

     @selector指令创建的是在编译时;-静态的方式

     NSSelectorFromString函数创建的则是在运行时;-动态的方式

     看起来没什么问题 但是编译器会给出一个警告:PerformSelector may cause a leak because its selector is unknown

        出现这个警告的原因是,如果找不到与该选择器匹配的方法,那么方法就会抛出异常,因而可能导致内存泄漏;

        可以通过添加pragma指令去除这个警告;

     如下述代码:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [cal performSelector:NSSelectorFromString(@"sumAddend1::") withObject:@1 withObject:@3];
#pragma clang diagnostic pop

     使用pragma指令 clang diagnostic ignored "功能诊断的名字" 可以禁止指定的编译器警告功能;

     使用#pragma clang diagnostic push和#pragma clang diagnostic pop,可以保存和恢复编译器当前的诊断设置;

        这可以确保编译器在编译源文件的其余部分时,继续执行正常的编译器选项;

     

     辅助理解:

     运行时包括较多的组成部分,编译器和运行时库都是其中的一部分;一般所说的静态处理是指编译器可判定的,而动态生成/调用则完全是由运行时其他部分决定的;

     OC提供了很多可以在运行时动态调用的方法;

     有@selector创建的SEL类型是静态创建的,但是使用的时候确是在运行时动态调用的;

     

     接下来再看一下运行时系统的其他特性;

     

     

     7.3 动态类型

     

     运行时系统通过动态类型(dynamic type)功能,可以在运行程序时决定对象的类型,因而可以使运行时因素能够在程序中指定使用那些对象;

     在事先无法知道变量分配哪种类型的对象的情况下,就特别有用;

     OC既支持静态类型 也支持动态类型:

        使用静态类型设置变量的类型时,变量的类型就由它的声明决定;

     

     动态类型与静态类型:

        对于静态类型,编译器能在编译时检查类型,执行程序前可以检查出类型错误;

        对于动态类型,类型检查操作是在运行时执行的;

        OC通过id数据类型支持动态类型;(id是OC独有的一种可以存储任何数据类型的OC对象的数据类型)


     动态类型变量的类型放到运行时确定,从而决定对象之间的关系,而不会强制它们使用静态编码;

        这样可以使编写一个可以处理任何类实例的方法变得容易的多,而无需在应用程序中为处理不同类编写多个不同种类的方法;

        使用动态类型可以简化接口;

        使用动态类型还可以提供很大的灵活性,可以在程序的执行过程中改进程序使用的数据类型,并在不重新编译和重新部署的情况下引入新的数据类型;

        在方法中还可以使用不同等级的类型信息,比如使用遵循某协议的对象作为参数,(id<xxxprotocal>);

     如:

        -(void)testMethod:(id<protocal>)para;

        -(void)testMethod:(NSNumber<protocal> *)para;

     

     OC还为运行时对象的内省提供了API(如检查动态设置类型的匿名对象属于哪个类),解决了部分静态类型检查问题;

        内省使运行时系统能够检查对象的类型,因而能够查明对象是否适用于特定的操作;

     

     我们休息一下,稍后进行后续介绍;



     

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS编程基础-OC(七)-运行时系统 的相关文章

  • iOS 8 UITableView 分隔符插入 0 不起作用

    我有一个应用程序 其中UITableView的分隔符插入设置为自定义值 右0 Left 0 这完美地适用于iOS 7 x 但是在iOS 8 0我看到分隔符插入设置为默认值15在右侧 即使在 xib 文件中它设置为0 它仍然显示不正确 我该如
  • 在哪里可以找到有关 IOS 日历同步的优秀教程? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在开发 iPhone 应用程序 如何将新事件与 iOS 日历同步 您可以浏览此 github 代码
  • 将深层链接传递到 iOS 模拟器?

    我想找到一种更简单的方法来在 iOS 模拟器中调用深层链接 在 Android 上 您可以使用 ADB 通过控制台将链接传输到模拟器中 是否有类似的方法或解决方法来打开最新 iOS 模拟器的深层链接 您可以在终端中输入以下内容 xcrun
  • AudioKit - 立体声通道从输入翻转到输出?

    我正在使用 AudioKit 创建一个实验性 iOS 音频应用程序 目前 我正在尝试将 AKStereoInput 的左声道重新路由到 AudioKit output 的右声道 并将 AKStereoInput 的右声道重新路由到输出的左声
  • 无法转换“String”类型的值?预期参数类型“URL”

    我正在尝试从主包中的文件加载数据 当我使用这段代码时 let path Bundle main path forResource abc ofType txt let dataTwo try Data contentsOf path err
  • Swift 3 的 NSLog 问题

    迁移到 Swift 3 后 当我尝试执行以下操作时出现错误 self publicDB save listRecord completionHandler record error gt Void in if let saveError e
  • 如何在 iOS 中通过 3G 连接创建无线热点

    如果我愿意 我将如何创建一个像这样的应用程序MyWi http intelliborn com mywi html 即 WiFi 网络共享应用程序 实现该功能需要哪些步骤 我需要使用哪些框架 库 我们的目标不是尝试将此应用程序放入应用程序商
  • 如果 UIGestureRecognizer 触发,如何取消按钮点击?

    更新 问题似乎是对另一个 GestureRecognizer 的依赖失败 请参阅此问题下面的评论和测试项目 在我的 iPhone 应用程序中 我有一个包含多个 UIButtons 作为子视图的视图 该视图还有一个 UITapGestureR
  • 如何使用 Javascript 从 Chrome iOS 下载 blob 文件?

    如何使用 Javascript 从 Chrome iOS 下载 blob 文件 我正在从 iOS 下载文件 pdf excel txt png iOS 没有文件系统 这对下载来说是一个问题 我创建了一个代码 根据操作系统和导航器 如果需要
  • 如何使 collectionViewCell 仅按高度自动调整大小?

    我使用collectionView的自动调整流布局的功能 self flow UICollectionViewFlowLayout alloc init self flow scrollDirection UICollectionViewS
  • 锁定时 AVAudioPlayer 在 iPhone 5 中不播放音频

    使用 AVAudioPlayer 我尝试在 iphone 播放器播放时播放声音 当设备锁定时也是如此 问题是 在 iPhone 4s ios 7 中 效果很好 但在带有 6 和 7 ios 的 iPhone 5 上没有任何反应 In the
  • MPMoviePlayerViewController,删除 Quicktime 符号/添加背景图像?

    我有一个播放音频的 MPMoviePlayerViewController 我想删除 Quicktime 徽标和 或向播放器添加自定义背景图像 但保留播放控件 我发誓我在 iOS 5 之前就已经这样做过 但我无法重新弄清楚 我尝试过的事情
  • swift:移动动画

    我在故事板中有 viewController 还有4个正方形 我想将我的方块放在视图中 首先我想显示两个正方形 如果我按下按钮 我希望我的红色 2 个方块向左移动 然后显示接下来的 2 个蓝色方块 就像这部动画 我需要创建一个scrollV
  • Xcode 8.2.1 无法添加文件夹引用

    我的 Xcode 8 2 1 不允许我添加文件夹引用 我尝试过的 我右键单击名为 Unity 的文件夹 然后单击 将文件添加到项目 在选项下选中 创建文件夹引用 我的文件夹被添加为红色文件 而不是通常的蓝色文件夹 我尝试将文件的 类型 更改
  • Objective C - 动态属性的respondsToSelector

    我目前面临的问题是检查对象 NSManagedObject 的属性是否存在 不幸的是方法 MyObject class respondsToSelector selector myProperty 总是返回NO 我认为这是因为CoreDat
  • Swift 每 5 天重复一次 LocalNotification

    如何每 5 天上午 10 00 重复一次 LocalNotification 我尝试这个 但它不起作用 let content UNMutableNotificationContent content title Hello content
  • 电话号码的 Swift 2 国家/地区代码

    我正在尝试从 iPhone 用户处获取国家 地区代码 我不确定是否有有关该国家 地区以及某些应用程序 如 Viber 如何建议拨号代码的信息 我到目前为止 let currentLocale NSLocale currentLocale l
  • 当设备方向改变时以编程方式更新约束的正确方法?

    我在用着storyboard and autolayout 并将 IB 中的约束设置为IBOutlet在相应的视图控制器中 我正在阅读几篇关于如何将纵向和横向的约束更新为不同的帖子 但我仍然不确定应该如何执行此操作 我应该设置新的限制吗 v
  • 允许在 Safari 上聊天应用程序使用 audio.play()

    由于苹果禁用了自动播放音频的功能HTMLMedia Element play https developer mozilla org en US docs Web API HTMLMediaElement play在没有用户交互的 java
  • MapKit 注释未显示在地图上

    我无法让 MKAnnotationViews 显示在 MapKit 的地图上 我正在使用 iOS 7 现在已经在论坛和网络上搜索了很多小时 尝试不同的示例和设置 下面我有 我认为 使其工作的最基本的设置 该应用程序包含一个 ViewCont

随机推荐

  • MySQL性能调优的10个方法

    1 选择合适的存储引擎 InnoDB 除非你的数据表使用来做只读或者全文检索 相信现在提到全文检索 没人会用 MYSQL 了 你应该默认选择 InnoDB 你自己在测试的时候可能会发现 MyISAM 比 InnoDB 速度快 这是因为 My
  • java 实现邮箱发送邮件功能(端口:465、587)

    使用465端口对邮件进行ssl加密传输 package com example alysslEmail import java security Security import java util Date import java util
  • 解决Eclipse里的注释中文错位问题

    2018年6月之后的eclipse版本 会出现中文注释字体不一 且缩进不一致的问题 如下 解决Eclipse里的注释中文错位问题如下 强迫症请收藏 1 Window gt Preference 2 输入formatter 选择如下 然后Ed
  • 计算机网络之物联网的特点及其主要应用领域

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 目录 前言 一 物联网的概念及其特点 1 1 物联网的概念 1 2 物联网的特点 二 物联网的分类及其主要应用领域 总结 前言 物联网是新一代信息技术的重要组成部分 也是信息
  • openGL之API学习(一九九)纹理单元和纹理对象的关系

    glGenTextures产生的是纹理对象 简称纹理 纹理单元数量在GPU上确定的 不需要创建 glBindTexture将纹理对象绑定到当前纹理单元的的目标类型上 一个纹理单元可以有多个类型1D 2D等 一个纹理对象能够绑定到多个目标类型
  • 不需要带手机直接选择刷脸支付

    刷脸成为了现实 各地实行刷脸的试点都取得成功 刷脸也就这样的走进我们的生活 不需要带手机 钱包 直接选择刷脸 当然 方便的还是无须等待排队 原本一个收银台需要配备一名收银员 所以考虑人力成本收银柜台数量是有限的 刷脸支付需要经历的步骤 不到
  • uniapp 调用蓝牙接收数据、发送指令后接收返回结果

    uniapp 调用蓝牙接收数据 向设备发送指令后接收返回结果 一 连接蓝牙设备 1 初始化蓝牙 2 搜索蓝牙 3 获取设备列表 4 连接设备 二 接收数据 1 获取设备服务列表 2 获取蓝牙特征 3 接收设备数据 三 向设备发送数据 并接收
  • 微服务及其框架是什么

    要理解微服务 首先要先理解不是微服务的那些 通常跟微服务相对的是单体应用 即将所有功能都打包成在一个独立单元的应用程序 从单体应用到微服务并不是一蹴而就的 这是一个逐渐演变的过程 本文将以一个网上超市应用为例来说明这一过程 目录 1 单体
  • js中的日期Date操作——获取当前日期 yyyy-mm-dd格式

    getCurrentDate const date new Date const year date getFullYear toString const month 0 date getMonth 1 slice 2 const day
  • AD操作小技巧总结

    1 群操作修改元器件属性 使用寻找相同的元器件来统一修改值 最重要一步是找到后用shift选中你需要的那几个 修改完后按enter键即可 根据下图可以知道筛选的条件有很多 也可以从不同的文件中去寻找元器件 2 将PCB中元器件旋转任意角度
  • 逐渐从土里长出来的小花

    从土里逐渐长出来的小花 这是长出来后的样子 图片压缩了出现了重影 代码在这里
  • Tornado中文教程

    Tornado 是一个Python web框架和异步网络库 起初由 FriendFeed 开发 通过使用非阻塞网络I O Tornado可以支撑上万级的连接 处理 长连接 WebSockets 和其他需要与每个用户保持长久连接的应用 相关链
  • 记录使用flask+socket+mongodb页面P标签的刷新

    1 flask的学习 随便百度个flask入门教程熟悉一下flask的启动 路由等 2 mondodb的学习 同1 3 socket的学习 同1 4 碰到的问题 4 1socket阻塞 使用 from threading import Th
  • 【全文检索_10】Filebeat 基本使用

    1 1 简介 1 1 1 概述 Filebeat 是 Beats 的一员 用于转发和集中日志数据的轻量级传送工具 当面对成百上千 甚至成千上万的服务器 虚拟机和容器生成的日志时 Filebeat 将为您提供一种轻量型方法 监视指定的日志文件
  • 网络数据传输的封装

    数据封装 Data Encapsulation 是指将协议数据单元 PDU 封装在一组协议头和尾中的过程 在OSI七层参考模型中 每层主要负责与其它机器上的对等层进行通信 该过程是在协议数据单元 PDU 中实现的 其中每层的PDU一般由本层
  • QString编码转换

    QString是QT中对于字符串的存储和处理的类 类似于MFC中的CString 如果用过的话就知道比std中的string和wstring要好用的多 功能也更强大 QString内部是将字符串保存为Unicode编码的 所以无论传入的字符
  • 【pytest】 标记冒烟用例 @pytest.mark.smoke

    1 使用 pytest mark smoke 标记用例 import pytest class Test Smoke def test 01 self assert 1 1 2 pytest mark smoke def test 02 s
  • OpenOCD介绍以及上手

    Versaloon支持AVR和AVR32的方式是模仿JTAGICE mkII 所以使用上相对简单很多 只是使用官方的开发环境即可 但Versaloon对ARM的支持是通过OpenOCD来实现 OpenOCD目前在国内还是非常少使用的 可能中
  • js文件下载 (url下载,监听进度)视频下载、图片下载、apk下载

    此下载功能针对文件是url 例如http xxxx 图片 jpg http xxx 视频 mp4 http xxx 应用 apk等等 可以监听进度 失败等等 function downFile url name var xhr new XM
  • iOS编程基础-OC(七)-运行时系统

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 第7章 运行时系统 终于到了运行时这一章 让我们来一步一步揭开它神秘的面纱吧 OC拥有相当多的动态特性 这些特性在运行程序时发挥作用 而不是在编译或链接代码时发挥作用