`
yehoubin
  • 浏览: 24286 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

IOS高级教程2:反射根据变量的引用获取变量名(转载)

    博客分类:
  • IOS
ios 
阅读更多

一、使用介绍

    项目有的时候,会遇到一些特殊的处理,想要根据一个实例的引用,获取这个实例在代码中的名称。比如在处理View的坐标的时候,我们将UIView的坐标信息配置到plist文件中,我们可以设置一个key,再通过这个key来获取配置文件中的坐标等信息。有没有更简单的方法呢,或者我只想简单的用实例变量的变量名做为key。下面就介绍一种简单的,根据实例变量的引用获取实例变量名的办法。

转载请保留原本链接:http://my.oschina.net/taptale/blog/110626

二、引用文件

    第一步,我们需要引入我们需要的头文件,在需要使用的类中引用下面代码

1
#import <objc/runtime.h>

 

三、运行原理

    我们可以从苹果官方的开发文档中查看到详细的运行时的使用方法及API,官方并没有直接提供根据实例的引用获取实例变量名称的办法,所以我们需要自己去实现。

 在官方的API中我们可以找到以下几个方法

    (1)Describes the instance variables declared by a class.    

Ivar * class_copyIvarList(Class cls, unsigned int *outCount)        

      (2) Reads the value of an instance variable in an object.

 

 id object_getIvar(id object, Ivar ivar)

     (3) Returns the name of an instance variable.

 

const char * ivar_getName(Ivar ivar)
根据以上的API,我们可以根据变量的拥有者获取所有变量的Ivar,再迭代所有Ivar,每一次迭代做如下操作
  • 根据(2)中的API,我们可以获取到当前迭代中的Ivar对应的实例变量的引用
  • 将获取到的实例变量与传递过来的实例变量的地址比较
  • 如果地址相同,说明当前的Ivar为传递过来实例变量的Ivar,可以通过(3)获取变量的名称并返回

四、代码

(1)根据上面的原理我们可以得到第一版本的代码,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (NSString *)nameWithInstance:(id)instance
{
    unsigned int numIvars = 0;
    NSString *key=nil;
    Ivar * ivars = class_copyIvarList([self.target class], &numIvars);
    for(int i = 0; i < numIvars; i++) {
        Ivar thisIvar = ivars[i];
        if ((object_getIvar(self.target, thisIvar) == instance)) {
            key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
            break;
        }
    }
    free(ivars);
    return key;
 
}

(2)在测试中发现到达上面的if语句的时候,程序有的时候就会crash,经详细测试发现,每次迭代到非objective-c对象的时候,如基本数据类型,BOOL、int、float就会报错。

原因出在object_getIvar这个方法中,当遇到非objective-c对象时,并直接crash,后来查看官方解释

 

The value of the instance variable specified by ivar, or nil if object is nil.

并没有明确的给出遇到非对象时会crash,也并不会返回nil

我们需要进行一下修正,当遇到非objective-c的时候,需要跳过执行。最终代码如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (NSString *)nameWithInstance:(id)instance
{
    unsigned int numIvars = 0;
    NSString *key=nil;
    Ivar * ivars = class_copyIvarList([self.target class], &numIvars);
    for(int i = 0; i < numIvars; i++) {
        Ivar thisIvar = ivars[i];
        const char *type = ivar_getTypeEncoding(thisIvar);
        NSString *stringType =  [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
        if (![stringType hasPrefix:@"@"]) {
            continue;
        }
        if ((object_getIvar(self.target, thisIvar) == instance)) {
            key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
            break;
        }
    }
    free(ivars);
    return key;
 
}
分享到:
评论

相关推荐

    iOS KVC实现原理

    2. **寻找getter/setter方法**:如果实例变量不存在,KVC会查找与键名匹配的getter(`- (id)valueForUndefinedKey:`)和setter(`- (void)setValue:forUndefinedKey:`)方法。默认情况下,这些方法会抛出异常,但在...

    iOS开发Runtime的用法

    Runtime处理Block的内存管理,包括栈Block的拷贝到堆以及捕获变量的强引用问题。 Runtime的深入理解和使用,能够极大地提高iOS开发的灵活性和效率。但同时,也需要注意,过度使用Runtime可能会降低代码的可读性和可...

    ios应用类项目

    在iOS应用开发中,我们经常会遇到各种技术和概念,这些都在标题和描述中有所提及。以下是对这些知识点的详细解释: 1. **webView**: `UIWebView`(或在iOS 8之后的`WKWebView`)是iOS应用中用于展示网页内容的关键...

    ios-Runtime.zip

    7. **反射(Reflection)**:Runtime提供了反射能力,使得程序能够自我检查,获取自身结构信息。这在调试、日志记录、序列化、插件系统等方面非常有用。 8. **分类 Categories**:Runtime支持类别,允许开发者为已有...

    KVC的原理和使用

    **KVC(Key-Value Coding)是iOS开发中的一个重要概念,它是Apple的Cocoa和Cocoa Touch框架中的一种数据访问机制。KVC提供了一种间接访问对象属性的方式,无需使用点语法或setter/getter方法。在本文中,我们将深入...

    ios-Runtime的实际使用场景.zip

    在iOS开发中,Objective-C的运行时(Runtime)是一个强大的工具,它允许我们在程序运行时动态地修改类、对象和方法。"ios-Runtime的实际使用场景.zip"中的资源,特别是"MMRuntime使用场景",旨在展示Runtime在实际...

    objective-c教程

    Objective-C是一种广泛用于iOS应用...总而言之,Objective-C教程通过基础的语法介绍到高级的设计模式和框架使用,为初学者提供了一条清晰的学习路径,从零开始直至成为能够熟练使用Objective-C进行iOS开发的程序员。

    IOS 中runtime使用方法整理

    在例子中,我们为`ClassOne`添加了一个名为`testClassOneWithArg1:arg2:arg3:`的方法,并指定了对应的实现(`IMP`)。`IMP`是方法实现的函数指针,这里使用了`TestClassOne`函数作为实现。然后,我们可以通过对象...

    object c语法总结

    - **反射**:一种允许程序在运行时获取对象信息的技术。 #### 条件编译与MVC模式 - **条件编译**:允许根据特定条件包含或排除代码片段。 - **MVC模式**:Model-View-Controller设计模式,广泛应用于iOS应用程序中...

    雷达驱动 A2 SDK

    8. **多平台支持**:根据SDK的具体设计,可能支持多种操作系统,如Windows、Linux、iOS和Android,使得开发者能够在不同平台上构建和运行雷达应用。 9. **实时性**:雷达驱动A2 SDK能够提供实时的雷达数据流,这...

    j2objc-dagger:使用 J2Objc 对 Dagger2 进行测试翻译

    **标题解析:**"j2objc-dagger"指的是一个项目,它关注的是如何利用J2ObjC工具对Dagger2这个依赖注入框架进行翻译,以便在iOS平台上进行测试或运行。这里的“测试翻译”可能意味着将Java代码转换为Objective-C,以...

    Object-C语言教程&案例&相关项目资源

    ### Objective-C语言教程&案例&相关项目资源 #### 基础信息 Objective-C是一种通用且面向对象的编程语言,它在C语言的基础上增加了面向对象的功能。这种语言最初由Brad Cox和Tom Love在20世纪80年代初期开发,并...

    Runtime 学习详解

    - **反射(Reflection)**:Runtime提供了`class_forName:`、`object_getClass:`等函数,可以在运行时获取类信息,实现对对象类型的检查和操作。 - **动态类型(Dynamic Typing)**:Objective-C允许在运行时改变...

    ObjC.pdf官方文档

    它是苹果iOS和macOS操作系统的主要开发语言之一。Objective-C结合了C语言的语法和Smalltalk式的面向对象特性,支持类、对象、消息传递等概念。 #### 二、对象、类与消息传递 **1. 对象与类:** - **对象**是类的一...

    c#开发设计

    9. **反射**:反射允许运行时动态地获取类型信息并创建对象,这对于插件架构和元编程有重要作用。 10. **单元测试与持续集成**:在C#开发中,使用诸如NUnit或xUnit的单元测试框架进行测试驱动开发是提高代码质量的...

    runtime源码

    Apple的runtime源码是Objective-C编程语言的核心组成部分,它提供了对象生命周期管理、消息传递机制以及类型系统的关键实现。...对于希望成为iOS或macOS平台的高级开发者来说,这是一块必不可少的知识领域。

    Objective-C 2.0 运行时系统编程指南

    6. **反射(Reflection)**:Objective-C的运行时系统提供了反射能力,允许代码在运行时检查自身结构,包括类、对象、方法等信息。`NSMethodSignature`和`NSInvocation`等工具类提供了获取和调用方法的能力,这对于...

    kotlin-docs

    - **反射**:运行时获取和操作类型信息。 - **类型安全构建器**:确保创建对象的过程不会遗漏必要的步骤。 #### 十一、多平台项目 Kotlin 支持开发跨平台应用程序,可以在多个平台上共享相同的逻辑代码: - **...

    kotlin-docs.pdf

    - **反射**:解释了如何在运行时获取类型信息和元数据。 - **类型安全的构建器**:介绍了一种机制,可以确保构造复杂对象时不会遗漏任何必要部分。 #### 参考资料 - **语法**:提供了 Kotlin 语法的完整规范。 - *...

    kotlin-reference-chinese

    - **反射**:Kotlin提供了反射API,用于在运行时获取类型信息和操作对象。 - **类型安全的构建器**:类型安全的构建器可以确保对象在创建时就已经处于一致的状态。 - **类型别名**:类型别名可以为复杂的类型定义一...

Global site tag (gtag.js) - Google Analytics