返回

掌握iOS下不可枚举属性遍历的BUG,避免陷入BUG中

前端

iOS 开发中,我们常常需要遍历对象的属性,以获取或设置属性值。然而,在 iOS 14.5 之前,存在一个 BUG,导致遍历不可枚举属性时可能出现问题。

这个 BUG 的具体表现是,当我们使用 for-in 语法遍历对象的属性时,可能无法遍历出不可枚举属性。这可能会导致我们无法获取或设置这些属性的值,从而导致程序出现问题。

一、不可枚举属性

在介绍这个 BUG 之前,我们先来了解一下不可枚举属性。不可枚举属性是指在使用 for-in 语法遍历对象时,不会被遍历到的属性。这通常是因为这些属性是私有的,或者被标记为 @nonobjc,或者被标记为 @objc(methodName)

二、BUG 剖析

在 iOS 14.5 之前,存在一个 BUG,导致即使我们将不可枚举属性标记为 @objc,也无法在 for-in 语法中遍历这些属性。这是因为,在 iOS 14.5 之前,编译器会在生成二进制文件时将不可枚举属性从类的元数据中删除。因此,当我们在运行时使用 for-in 语法遍历对象的属性时,将无法找到这些不可枚举属性。

三、解决方案

在 iOS 14.5 中,苹果修复了这个 BUG。因此,在 iOS 14.5 及更高版本中,我们可以正常遍历不可枚举属性。但是,如果我们仍然需要在 iOS 14.5 之前的版本中遍历不可枚举属性,我们可以使用以下两种方法:

  1. 使用 NSEnumerator

我们可以使用 NSEnumerator 类来遍历对象的属性,包括不可枚举属性。具体方法如下:

Class cls = [YourClass class];
NSEnumerator *enumerator = [cls propertyNames];
while ((propertyName = [enumerator nextObject])) {
    NSLog(@"%@", propertyName);
}
  1. 使用 objc_property_t 结构体

我们也可以使用 objc_property_t 结构体来遍历对象的属性,包括不可枚举属性。具体方法如下:

unsigned int propertyCount;
objc_property_t *properties = class_copyPropertyList([YourClass class], &propertyCount);
for (unsigned int i = 0; i < propertyCount; i++) {
    objc_property_t property = properties[i];
    const char *propertyName = property_getName(property);
    NSLog(@"%@", [NSString stringWithUTF8String:propertyName]);
}
free(properties);

四、api-monitor 库介绍

api-monitor 是一个库,引入这个库,可自动上报服务端接口的耗时、接口错误信息、错误码、HTTP 状态码等信息,用于监控接口质量。

api-monitor 的使用非常简单,只需要在项目中导入 api-monitor 库,并在需要上报接口信息的地方调用 api-monitor 的相关方法即可。

api-monitor 库提供了丰富的功能,包括:

  • 自动上报服务端接口的耗时、接口错误信息、错误码、HTTP 状态码等信息
  • 支持自定义上报字段
  • 支持多种上报方式,包括 HTTP、HTTPS、UDP 等
  • 支持多种数据格式,包括 JSON、XML、Protobuf 等
  • 支持多种语言,包括 Objective-C、Swift、Java、Kotlin 等

五、总结

在 iOS 14.5 之前,存在一个 BUG,导致遍历不可枚举属性时可能出现问题。在 iOS 14.5 中,苹果修复了这个 BUG。因此,在 iOS 14.5 及更高版本中,我们可以正常遍历不可枚举属性。但是,如果我们仍然需要在 iOS 14.5 之前的版本中遍历不可枚举属性,我们可以使用 NSEnumerator 类或 objc_property_t 结构体。

同时,我们还介绍了一款名为 api-monitor 的库,该库可以自动上报服务端接口的耗时、接口错误信息、错误码、HTTP 状态码等信息,用于监控接口质量。