2013-04-09 93 views
0

我试图创建一个应用程序,从api中提取json,并提供一组关于界面的外观样式的说明。所以基本上,json将包含一个NSDictionary数组,每个NSDictionary将是一个显示在屏幕上的对象。以编程方式创建NSObjects ios

在NSDictionary中将显示如何显示对象的所有细节,如对象的类型,对象的位置和对象的大小。

我已经编写代码来接受一组按钮到屏幕。

for (int i = 0; i < self.jsonObjects.count; i++) { 
    NSDictionary *jsonObject = [self.jsonObjects objectAtIndex:i]; 
    if ([[jsonObject objectForKey:@"object"] isEqualToString:@"UIButton"]) { 
     UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 

     NSNumber *x = [jsonObject objectForKey:@"xlocation"]; 
     NSNumber *y = [jsonObject objectForKey:@"ylocation"]; 
     NSNumber *width = [jsonObject objectForKey:@"width"]; 
     NSNumber *height = [jsonObject objectForKey:@"height"]; 
     NSString *title = [jsonObject objectForKey:@"title"]; 
     [button setFrame:CGRectMake(x.intValue, y.intValue, width.intValue, height.intValue)]; 
     [button setTitle:title forState:UIControlStateNormal]; 
     [self.view addSubview:button]; 
    } 
} 

现在我可以为每个对象提供大量的if语句并让程序做同样的事情,但我试图避免它。

基本上我所要求的是实现这一点的最佳方式是尽量减少编码并提高代码的可读性。

这是我写的模仿json输出按钮的代码。

NSDictionary *button = [[NSDictionary alloc] initWithObjectsAndKeys:@"UIButton", @"object",@"PressMe",@"title",@"10",@"xlocation",@"10",@"ylocation",@"100",@"width",@"100",@"height", nil]; 

NSDictionary *button2 = [[NSDictionary alloc] initWithObjectsAndKeys:@"UIButton", @"object",@"Dont Press",@"title",@"10",@"xlocation",@"210",@"ylocation",@"100",@"width",@"100",@"height", nil]; 

self.jsonObjects = [[NSArray alloc] initWithObjects:button,button2, nil]; 

由于我仍然必须创建api,所以json输出可以非常灵活。我正想着有一个数组的数组。其中数组中的每个数组都是一组按钮或文本字段数组。那么我只需要大约20-30个数组来覆盖不同的对象类型,并且可以遍历主数组,然后遍历每个按钮或文本字段的数组。

为礼Ganem

object UIView * 0x07145c60 
UIResponder UIResponder 
_layer CALayer * 0x07145e80 
_tapInfo id 0x00000000 
_gestureInfo id 0x00000000 
_gestureRecognizers NSMutableArray * 0x00000000 
_subviewCache NSArray * 0x075213e0 
_charge float 0 
_tag NSInteger 0 
_viewDelegate UIViewController * 0x00000000 
_backgroundColorSystemColorName NSString * 0x00000000 
_viewFlags <anonymous struct> 
+1

坦率地说,坚果是开始编码,并丢弃前3-4次尝试。你最终会理解这些问题,并以合理的方式解决问题。 – 2013-04-09 12:15:03

回答

0

我建议封装代码:具有以下签名

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    NSNumber *x = [jsonObject objectForKey:@"xlocation"]; 
    NSNumber *y = [jsonObject objectForKey:@"ylocation"]; 
    NSNumber *width = [jsonObject objectForKey:@"width"]; 
    NSNumber *height = [jsonObject objectForKey:@"height"]; 
    NSString *title = [jsonObject objectForKey:@"title"]; 
    [button setFrame:CGRectMake(x.intValue, y.intValue, width.intValue, height.intValue)]; 
    [button setTitle:title forState:UIControlStateNormal]; 

在一个工厂方法:

- (UIButton*)butttonFromJSONDescription:(NSDictionary*)jsonObject; 

那么你的循环将成为:

if ([[jsonObject objectForKey:@"object"] isEqualToString:@"UIButton"]) { 
    [self.view addSubview:[self buttonFromJSONDescription:jsonObject]]; 
} else if ([[jsonObject objectForKey:@"object"] isEqualToString:@"UITextField"]) { 
    [self.view addSubview:[self textFieldFromJSONDescription:jsonObject]]; 
} 

我知道你想要管理的对象类有不同的属性,你可能想在JSON中设置。这似乎阻止了进一步的抽象。

0

您不应该创建数组的数组,或者有30个条件。 您应该根据反射的“object”值创建一个对象。 事情是这样的:

id object = [[NSClassFromString(jsonObject[@"object"]) alloc] init]; 

如果只发送的UIView的子类作为你的“对象”,那么你可以代替写:

UIView *object = (UIView*)[[NSClassFromString(jsonOnject[@"object"]) alloc] init]; 
NSNumber *x = [jsonObject objectForKey:@"xlocation"]; 
NSNumber *y = [jsonObject objectForKey:@"ylocation"]; 
NSNumber *width = [jsonObject objectForKey:@"width"]; 
NSNumber *height = [jsonObject objectForKey:@"height"]; 
[object setFrame:CGRectMake(x.intValue, y.intValue, width.intValue, height.intValue)]; 

写这首,只是为了看看它是如何工作:

UIView *myView = (UIView*)[[NSClassFromString(@"UISwitch") alloc] init]; 
myView.frame = CGRectMake(0,0,100,40); 
[self.view addSubview:myView]; 

为了改变对象的属性,迭代你的字典并执行必要的选择器。下面是一个例子来说明:

NSDictionary *jsonObject = @{@"setBackgroundColor:":[UIColor redColor]}; 
for (NSString *key in jsonObject) 
{ 
    if ([myView respondsToSelector:NSSelectorFromString(key)]) 
    { 
     [myView performSelector:NSSelectorFromString(key) withObject:jsonObject[key]]; 
    } 
} 
+0

所以我做到了,包括[self.view addSubview:object];但它不添加我的按钮。这是关于在我的控制台中创建的对象的详细信息。看我原来的帖子 – user1898829 2013-04-09 13:49:18

+0

UIButton是一个特例,因为你必须将它的类型设置为UIButtonTypeRoundedRect或任何其他类型才能看到它。先试试UISwirch,看看它是否有效。我会编辑我的答案... – 2013-04-10 08:14:20

+0

工作。有关如何包含大多数对象的任何建议。如果唯一的问题是按钮,那么我总是可以为按钮编写单独的代码。我只是不想写10个不同的对象。 – user1898829 2013-04-10 08:59:25

0

我刚实施类似于您在一个应用程序香港专业教育学院在做什么东西一直在努力。我所做的是有一个类型的json语句,然后是一组项目。调用这些对象SectionItems所以你将有一个整体的json数组SectionItems,你可以从json文件读入NSArray。然后我所做的是针对SectionItems可能存在的每种类型,您将创建一个自定义UITableViewCell。创建一个UITableDataSource,它将检查indexPath.row与从您的json文件中读入的SectionItems数组,该数组将使用SectionItems中的项目构造相应的UITableViewCell以显示该行。

所以只是为了清楚起见,这是我的SectionItems样子:

@interface SectionItem : NSObject 

@property (strong) NSString *type; //controls what type of cell will be made in the datasource 
@property (strong) NSString *data; //auxiliary data 
@property (strong) NSArray *items; //actual data to populate the cell with 

-(id) initWithJSON:(NSDictionary *)jsonData; 

@end 

希望这会有所帮助。我发现这种方式很有用,因为如果json中的数据发生改变,那么所有东西都可以正常工作。 json的形成方式完全控制着数据如何被查看。

0

您总是可以使用框架来执行读取/解析,请参阅this post

此外,如果您更喜欢更定制的方法,则可以使用objective-c运行时。我为最近的一个项目编写了一个dynamic mapper

例如,您可以为UIButton子类创建一个initWithDictionary:方法,该方法可以解析每个按钮的json集合 - 并且由于您声称对Web服务有很好的控制,所以还可以将大小字段和原始字段组合到一起一个代表矩形“{x,y,width,height}”的字符串,并且在你的initWithDictionary字段中,对于给定的'frame'键,将字符串转换为矩形CGRectFromString()