我试图创建一个应用程序,它从api中提取json,其中包含一组关于界面必须如何的说明。所以基本上json将包含一个NSDictionary数组,每个NSDictionary将是一个显示在屏幕上的对象。
在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个数组来覆盖不同的对象类型,并且可以运行主数组,然后遍历每个按钮或文本字段的数组。
为Eli 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>
答案 0 :(得分: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中设置的不同属性。这似乎阻止了进一步的抽象。
答案 1 :(得分:0)
您不应该创建数组数组,或者如果条件有30个数组。 您应该根据带有反射的“对象”的值创建一个对象。 像这样:
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]];
}
}
答案 2 :(得分:0)
我刚刚实现了类似于你在我正在开发的应用程序中所做的事情。我所做的是有一个类型的json语句,然后是一个项目数组。调用这些对象SectionItems
,这样你就可以得到一个整个json数组SectionItems
,你可以从json文件读入NSArray
。然后,我所做的是为SectionItems
创建自定义UITableViewCell
的每种类型。创建一个UITableDataSource
,它将根据您从json文件中读入的indexPath.row
数组检查SectionItems
,该文件将使用{中的项构建相应的UITableViewCell
{1}}显示在该行。
所以为了清楚起见,这就是我SectionItems
的样子:
SectionItems
希望这会有所帮助。我发现这种方式很有用,因为如果json中的数据发生了变化,一切都会正常工作。形成json的方式完全控制着数据的查看方式。
答案 3 :(得分:0)
您总是可以使用框架来进行提取/解析,请参阅this post。
此外,如果您更喜欢采用更具定制的方法,则可以使用objective-c运行时。我为最近的一个项目写了dynamic mapper。
例如,您可以对UIButton进行子类化,使用initWithDictionary:方法来解析每个按钮的json集合 - 并且因为您说您可以很好地控制Web服务,所以您还可以将大小和原始字段组合成一个表示rect“{x,y,width,height}”的字符串,以及initWithDictionary字段内的字符串,对于给定的“frame”键,将字符串转换为带有CGRectFromString()
的矩形