美文网首页OC Tips
NSArray-不一样的KVC

NSArray-不一样的KVC

作者: 旭宝爱吃鱼 | 来源:发表于2020-03-19 14:00 被阅读0次

我准备了一个用于测试的类Person

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

@end

我通过KVC的方式为name赋值和取值。

Person *person = [[Person alloc] init];
[person setValue:@"a" forKey:@"name"];
NSLog(@"%@", [person valueForKey:@"name"]);

// result: a

接下来,我对NSArray进行KVC操作。

Person *p1 = [[Person alloc] init];
p1.name = @"a";
p1.age = 10;
Person *p2 = [[Person alloc] init];
p2.name = @"b";
p2.age = 15;
    
NSArray *array = @[p1, p2];
id result = [array valueForKey:@"name"];
NSLog(@"%@", result);

这是什么操作?NSArray并没有name这个属性,结果肯定是valueForUndefinedKey:

看看真实的结果是什么。

(
    a,
    b
)

结果是一个数组?对,就是一个数组。仔细观察看看,p1.name == ap2.name == b

为什么呢?

来看看源码吧。

- (id) valueForKey: (NSString*)key
{
  id result = nil;

  if ([key isEqualToString: @"@count"] == YES)
    {
      result = [NSNumber numberWithUnsignedInteger: [self count]];
    }
  else if ([key isEqualToString: @"count"] == YES)
    {
      GSOnceMLog(
@"[NSArray-valueForKey:] called with 'count' is deprecated .. use '@count'");
      result = [NSNumber numberWithUnsignedInteger: [self count]];
    }
  else
    {
      NSMutableArray    *results = nil;
      static NSNull *null = nil;
      NSUInteger    i;
      NSUInteger    count = [self count];
      volatile id   object = nil;

      results = [NSMutableArray arrayWithCapacity: count];

      for (i = 0; i < count; i++)
        {
          id    result;

          object = [self objectAtIndex: i];
          result = [object valueForKey: key];
          if (result == nil)
            {
              if (null == nil)
        {
          null = RETAIN([NSNull null]);
        }
              result = null;
            }

          [results addObject: result];
        }

      result = results;
    }
  return result;
}

再来看看setValue:forKey:

- (void) setValue: (id)value forKey: (NSString*)key
{
  NSUInteger    i;
  NSUInteger    count = [self count];
  volatile id   object = nil;

  for (i = 0; i < count; i++)
    {
      object = [self objectAtIndex: i];
      [object setValue: value
        forKey: key];
    }
}

还有valueForKeyPath:

- (id) valueForKeyPath: (NSString*)path
{
  id    result = nil;

  if ([path hasPrefix: @"@"])
    {
      NSRange   r;

      r = [path rangeOfString: @"."];
      if (r.length == 0)
        {
          if ([path isEqualToString: @"@count"] == YES)
            {
              result = [NSNumber numberWithUnsignedInteger: [self count]];
            }
          else
            {
              result = [self valueForKey: path];
            }
        }
      else
        {
          NSString      *op = [path substringToIndex: r.location];
          NSString      *rem = [path substringFromIndex: NSMaxRange(r)];
          NSUInteger    count = [self count];

          if ([op isEqualToString: @"@count"] == YES)
            {
              result = [NSNumber numberWithUnsignedInteger: count];
            }
          else if ([op isEqualToString: @"@avg"] == YES)
            {
              double        d = 0;

              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  while ((o = [e nextObject]) != nil)
                    {
                      d += [[o valueForKeyPath: rem] doubleValue];
                    }
                  d /= count;
                }
              result = [NSNumber numberWithDouble: d];
            }
          else if ([op isEqualToString: @"@max"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      if (result == nil
                        || [result compare: o] == NSOrderedAscending)
                        {
                          result = o;
                        }
                    }
                }
            }
          else if ([op isEqualToString: @"@min"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      if (result == nil
                        || [result compare: o] == NSOrderedDescending)
                        {
                          result = o;
                        }
                    }
                }
            }
          else if ([op isEqualToString: @"@sum"] == YES)
            {
              double        d = 0;

              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  while ((o = [e nextObject]) != nil)
                    {
                      d += [[o valueForKeyPath: rem] doubleValue];
                    }
                }
              result = [NSNumber numberWithDouble: d];
            }
          else if ([op isEqualToString: @"@distinctUnionOfArrays"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  result = [NSMutableSet set];
                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      [result addObjectsFromArray: o];
                    }
                  result = [result allObjects];
                }
              else
                {
                  result = [NSArray array];
                }
            }
          else if ([op isEqualToString: @"@distinctUnionOfObjects"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  result = [NSMutableSet set];
                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      [result addObject: o];
                    }
                  result = [result allObjects];
                }
              else
                {
                  result = [NSArray array];
                }
            }
          else if ([op isEqualToString: @"@distinctUnionOfSets"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  result = [NSMutableSet set];
                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      [result addObjectsFromArray: [o allObjects]];
                    }
                  result = [result allObjects];
                }
              else
                {
                  result = [NSArray array];
                }
            }
          else if ([op isEqualToString: @"@unionOfArrays"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  result = [GSMutableArray array];
                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      [result addObjectsFromArray: o];
                    }
                  result = GS_IMMUTABLE(result);
                }
              else
                {
                  result = [NSArray array];
                }
            }
          else if ([op isEqualToString: @"@unionOfObjects"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  result = [GSMutableArray array];
                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      [result addObject: o];
                    }
                  result = GS_IMMUTABLE(result);
                }
              else
                {
                  result = [NSArray array];
                }
            }
          else if ([op isEqualToString: @"@unionOfSets"] == YES)
            {
              if (count > 0)
                {
                  NSEnumerator  *e = [self objectEnumerator];
                  id            o;

                  result = [GSMutableArray array];
                  while ((o = [e nextObject]) != nil)
                    {
                      o = [o valueForKeyPath: rem];
                      [result addObjectsFromArray: [o allObjects]];
                    }
                  result = GS_IMMUTABLE(result);
                }
              else
                {
                  result = [NSArray array];
                }
            }
          else
            {
              result = [super valueForKeyPath: path];
            }
        }
    }
  else
    {
      result = [super valueForKeyPath: path];
    }

  return result;
}

相关文章

  • NSArray-不一样的KVC

    我准备了一个用于测试的类Person。 我通过KVC的方式为name赋值和取值。 接下来,我对NSArray进行K...

  • TableView的添加删除

    步骤 模型数据从NSArray->NSMutableArray 在故事板(Storyboard)中添加 增加按钮 ...

  • iOS原理篇(二): KVC实现原理

    KVC实现原理 什么是 KVC KVC基本使用 KVC 原理 总结 一 、 什么是KVC KVC的全称是Key-V...

  • KVC详解

    KVC 目录结构KVC定义KVC取值和设置KVC使用keyPathKVC处理字典KVC作用 参考:iOS KVC和...

  • 19.iOS底层学习之iOS底层学习之KVC

    本篇提纲1、KVC的基本介绍2、KVC的API3、KVC的写入过程4、KVC的读取过程5、自定义KVC KVC的基...

  • KVC,KVO

    KVC , KVO KVC和KVO的区别及应用 KVC/KVO原理 1. KVC键值编码 KVC,即是指NSKey...

  • iOS 关于KVC的一些总结(转)

    原文:iOS 关于KVC的一些总结 本文参考: KVC官方文档 KVC原理剖析 iOS KVC详解 KVC 简介 ...

  • OC语法:KVC的底层实现

    一、KVC是什么二、怎么使用KVC三、KVC的底层实现四、KVC常见面试题 一、KVC是什么 KVC全称Key-V...

  • iOS 关于KVC的一些总结

    本文参考: KVC官方文档 KVC原理剖析 iOS KVC详解 KVC 简介 KVC全称是Key Value Co...

  • KVC的简单使用

    KVC字典转模型 KVC 中经常使用的就是字典转模型 KVC的大招 KVC设置对象属性及取值 KVC间接设置对象属...

网友评论

    本文标题:NSArray-不一样的KVC

    本文链接:https://www.haomeiwen.com/subject/tfxlyhtx.html