2013-04-09 88 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()