从带有属性的NSObject转换为NSDictionary的Obj-C简单方法?

jam*_*rns 14 objective-c nsdictionary ios

我遇到了一些我最终想到的东西,但认为可能有一种更有效的方法来实现它.

我有一个对象(一个采用MKAnnotation协议的NSObject),它有许多属性(标题,副标题,纬度,经度,信息等).我需要能够将此对象传递给另一个对象,该对象希望使用objectForKey方法从中提取信息,作为NSDictionary(因为这是从另一个视图控制器获取的内容).

我最终做的是创建一个新的NSMutableDictionary并在其上使用setObject:forKey来传输每条重要信息,然后我只传递新创建的字典.

有没有更简单的方法来做到这一点?

这是相关的代码:

// sender contains a custom map annotation that has extra properties...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{    
    if ([[segue identifier] isEqualToString:@"showDetailFromMap"]) 
{
    DetailViewController *dest =[segue destinationViewController];

    //make a dictionary from annotaion to pass info
    NSMutableDictionary *myValues =[[NSMutableDictionary alloc] init];
    //fill with the relevant info
    [myValues setObject:[sender title] forKey:@"title"] ;
    [myValues setObject:[sender subtitle] forKey:@"subtitle"];
    [myValues setObject:[sender info] forKey:@"info"];
    [myValues setObject:[sender pic] forKey:@"pic"];
    [myValues setObject:[sender latitude] forKey:@"latitude"];
    [myValues setObject:[sender longitude] forKey:@"longitude"];
    //pass values
    dest.curLoc = myValues;
    }
}
Run Code Online (Sandbox Code Playgroud)

提前感谢您的集体智慧.


这是我想出来的,感谢下面的人们......

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{    
if ([[segue identifier] isEqualToString:@"showDetailFromMap"]) 
{
    DetailViewController *dest =[segue destinationViewController];
    NSArray *myKeys = [NSArray arrayWithObjects:
@"title",@"subtitle",@"info",@"pic",@"latitude",@"longitude", nil];

    //make a dictionary from annotaion to pass info
    NSDictionary *myValues =[sender dictionaryWithValuesForKeys:myKeys];

    //pass values
    dest.curLoc = myValues;
}
Run Code Online (Sandbox Code Playgroud)

}

更简单的修复,如下所示......

使用valueForKey而不是object来检索信息.


Ric*_*III 57

当然可以!使用objc-runtime和KVC!

#import <objc/runtime.h>

@interface NSDictionary(dictionaryWithObject)

+(NSDictionary *) dictionaryWithPropertiesOfObject:(id) obj;

@end
@implementation NSDictionary(dictionaryWithObject)

+(NSDictionary *) dictionaryWithPropertiesOfObject:(id)obj
{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];

    unsigned count;
    objc_property_t *properties = class_copyPropertyList([obj class], &count);

    for (int i = 0; i < count; i++) {
        NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
        [dict setObject:[obj valueForKey:key] forKey:key];
    }

    free(properties);

    return [NSDictionary dictionaryWithDictionary:dict];
}

@end
Run Code Online (Sandbox Code Playgroud)

你会这样使用:

MyObj *obj = [MyObj new];    
NSDictionary *dict = [NSDictionary dictionaryWithPropertiesOfObject:obj];
NSLog(@"%@", dict);
Run Code Online (Sandbox Code Playgroud)

  • 您也可以从运行时获取密钥,并使用`NSKeyValueCoding`中的`-dictionaryWithValuesForKeys:`.或者您直接使用硬编码的键列表,因为您可能不希望字典中的*every*属性. (2认同)

iHS*_*iHS 11

这是一篇老帖子,Richard J. Ross III的答案非常有用,但是在自定义对象的情况下(自定义类中有另一个自定义对象).但是,有时属性是其他对象等,使序列化有点复杂.

Details * details = [[Details alloc] init];
details.tomato = @"Tomato 1";
details.potato = @"Potato 1";
details.mangoCount = [NSNumber numberWithInt:12];

Person * person = [[Person alloc]init];
person.name = @"HS";
person.age = @"126 Years";
person.gender = @"?";
person.details = details;
Run Code Online (Sandbox Code Playgroud)

为了将这些类型的对象(多个自定义对象)转换为字典,我不得不修改Richard J. Ross III的答案.

+(NSDictionary *) dictionaryWithPropertiesOfObject:(id)obj
{
  NSMutableDictionary *dict = [NSMutableDictionary dictionary];

  unsigned count;
  objc_property_t *properties = class_copyPropertyList([obj class], &count);

  for (int i = 0; i < count; i++) {
      NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
      Class classObject = NSClassFromString([key capitalizedString]);
      if (classObject) {
        id subObj = [self dictionaryWithPropertiesOfObject:[obj valueForKey:key]];
        [dict setObject:subObj forKey:key];
      }
      else
      {
        id value = [obj valueForKey:key];
        if(value) [dict setObject:value forKey:key];
      }
   }

   free(properties);

   return [NSDictionary dictionaryWithDictionary:dict];
}
Run Code Online (Sandbox Code Playgroud)

我希望它能帮助别人.完全归功于Richard J. Ross III.


Pau*_*l.s 5

如果属性都有相同的名称作为关键字用于访问字典,那么你可以只使用KVC,不得不valueForKey:代替objectForKey

例如给定这本字典

NSDictionary *annotation = [[NSDictionary alloc] initWithObjectsAndKeys:
                             @"A title", @"title", nil];
Run Code Online (Sandbox Code Playgroud)

和这个对象

@interface MyAnnotation : NSObject

@property (nonatomic, copy) NSString *title;

@end
Run Code Online (Sandbox Code Playgroud)

有字典的实例还是MyAnnotation可以调用都没关系

[annotation valueForKey:@"title"];
Run Code Online (Sandbox Code Playgroud)

显然,其他方式也可以,例如

[annotation setValue:@"A title" forKey:@"title"];
Run Code Online (Sandbox Code Playgroud)