【问题标题】:Create dynamic form UI using JSON in iOS在 iOS 中使用 JSON 创建动态表单 UI
【发布时间】:2014-11-26 08:46:18
【问题描述】:

我需要使用 JSON 创建一个动态表单。我已经解析了 JSON,但我不知道如何动态创建表单。 我正在获取带有一些控件的 json 数据,例如复选框、文本字段和问题,现在我想根据那里的 Question 创建 From。 类似于我们如何使用 Google 表单创建一个。 请查看以下链接https://docs.google.com/forms/d/1lPn1aSvJsiDbJchsJjwsC93tWizXhj1qWkFPygt3oU4/viewform 请推荐一些代码或教程。

【问题讨论】:

    标签: ios


    【解决方案1】:

    我的想法是分步进行

    1) 创建模型类示例

         class UIControl
         {
              NSString *strControlName;
              NSString *strControlType;
              NSString *strControlValue;
              Bool  isSelected;
         }
    

    2) 解析json并创建模型类对象

    3) 将模型类对象添加到 arrOfControls

    4) 要么使用表格视图,要么只使用循环遍历整个 arrOfControls

    5) 以防万一,表格视图检查 cellForRowAtIndexPath 类型的控件。

    6) 为您的 JSON 数据可能附带的每个可能的字段创建自定义单元格。

    7) 根据控件类型返回委托函数(cellForRowAtIndexPath)中的自定义单元格。例如:-

             if([[arrOfControls objectAtIndexPath:indexPath.row] strType] isEqualToString:@"TextField"]])
              {
                     //create object of customcell for textfield and return cell
               }
              else if([[arrOfControls objectAtIndexPath:indexPath.row] strType] isEqualToString:@"CheckBox"]])
              {
                     //create object of customcell for checkbox and return cell
              }
              else
              {
                    //control type if not match any of the above
              }
    

    这是粗略的想法而不是实际的代码。 我的项目中的一些代码,用于 cellForRowAtIndexPath

           if(indexPath.section==0)
        {
            FormField *currControl=[fieldArray objectAtIndex:indexPath.row];
            if(([currControl.strFieldType caseInsensitiveCompare:@"TextLabel"]==NSOrderedSame )|| [currControl.strFieldType caseInsensitiveCompare:@"Text"]==NSOrderedSame)
            {
                TextFieldWithLabelTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellTextFieldWithLabel"];
                cell.txtTextField.delegate=self;
                [cell.txtTextField setTag:indexPath.row];
                if([currControl strFieldValue]==nil)
                {
                    cell.txtTextField.text = @"";
                    [cell.txtTextField setPlaceholder:[currControl strPlaceHolder]];
                }
                else
                {
                    //if save value exists
                    cell.txtTextField.text=@"";
                    cell.txtTextField.text=[currControl strFieldValue];
                }
                cell.lblTextFieldIdenti.text=[[fieldArray objectAtIndex:indexPath.row] strFieldName];
                if([currControl.strFieldType caseInsensitiveCompare:@"Text"]==NSOrderedSame)
                {
                    cell.lblTextFieldIdenti.text=@"";
                }
                [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
                return cell;
            }
            else if(([currControl.strFieldType caseInsensitiveCompare:@"TextView"]==NSOrderedSame)||([currControl.strFieldType caseInsensitiveCompare:@"TextViewWithCam"]==NSOrderedSame))
            {
                TableViewTextAreaCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TableViewTextAreaCell"];
                cell.txtView.delegate=self;
                cell.txtView.text=@"";
                if([currControl strFieldValue]!=nil)
                {
                    //if save value exists
                    cell.txtView.text=@"";
                    cell.txtView.text=[currControl strFieldValue];
                }
                cell.fieldLabel.text=[[fieldArray objectAtIndex:indexPath.row] strFieldName];
                NSMutableArray *barItems = [[NSMutableArray alloc] init];
                UIToolbar* keyboardDoneButtonView = [[UIToolbar alloc] init];
                keyboardDoneButtonView.barStyle = UIBarStyleDefault;
                keyboardDoneButtonView.translucent = NO;
                keyboardDoneButtonView.barTintColor=[UIColor colorWithHue:0.6 saturation:0.33 brightness:0.69 alpha:0];
                [keyboardDoneButtonView sizeToFit];
                UIBarButtonItem *leftFlexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
                [barItems addObject:leftFlexSpace];
                UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"BTN_DONE", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(pickerDoneClicked:)];
    
                [barItems addObject:btnDone];
                [keyboardDoneButtonView setItems:barItems animated:YES];
                [cell.txtView setInputAccessoryView:keyboardDoneButtonView];
    
                [cell configureCell:currControl.strFieldName];
                cell.fieldLabel.textColor=[UIColor darkTextColor];
                cell.txtView.backgroundColor =[UIColor colorWithHexString:@"#f3f1f2"];
                cell.fieldLabel.font=[UIFont systemFontOfSize:12];
                cell.selectionStyle=UITableViewCellSelectionStyleNone;
                [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
                [cell.imgViewCam setHidden:TRUE];
                if([currControl.strFieldType caseInsensitiveCompare:@"TextViewWithCam"]==NSOrderedSame)
                {
                    UITapGestureRecognizer *singleTap =  [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(CameraClicked:)];
                    [singleTap setNumberOfTapsRequired:1];
                    [cell.imgViewCam addGestureRecognizer:singleTap];
                    [cell.imgViewCam setHidden:FALSE];
    
                }
                return cell;
            }
            else if([currControl.strFieldType caseInsensitiveCompare:@"DropDown"]==NSOrderedSame)
            {
                //if dropdwon box
                DropDownTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellDropDown"];
                cell.lblDropDownidentifier.text=[currControl strFieldName];
                [cell.btnDropDown setTag:indexPath.row];
                [cell.btnDropDown addTarget:self action:@selector(ShowOptions:) forControlEvents:UIControlEventTouchUpInside];
                [cell.btnDropDown setTitle:@"" forState:UIControlStateNormal];
    
    
                if([currControl strFieldValue]!=nil)
                {
                    [cell.btnDropDown setTitle:[currControl strFieldValue] forState:UIControlStateNormal];
                }
                [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
                if([[currControl strFieldName] caseInsensitiveCompare:@"Time Of Delivery:"]==NSOrderedSame)
                {
                    cell.imgDropDown.image=[UIImage imageNamed:@"stopwatch.png"];
                }
                else if([[currControl strFieldName] caseInsensitiveCompare:@"Date Of Delivery:"]==NSOrderedSame)
                {
                    cell.imgDropDown.image=[UIImage imageNamed:@"calendar.png"];
                }
                else
                {
                    cell.imgDropDown.image=[UIImage imageNamed:@"dropdown.jpeg"];
                }
    
                return cell;
    
            }
    

    【讨论】:

    • 是的,我有,但它是巨大的代码。这对我的公司来说是机密的
    • 确定如何取回控件的输入值
    • 我的意思是如果用户在文本字段中输入一些值如何获得所有值
    • 如果是文本字段,textFieldDidEndEditing:(UITextField *)textField。将文本字段值保存到模型类成员 strValue 并更新数组。
    • 但是他们可以给我更多的不仅仅是一个文本文件,而不仅仅是文本字段我想要所有控件的值
    【解决方案2】:

    这是我发现很有趣的东西并进行了快速搜索。根据您的 JSON 中包含的内容,我可以看到实现此目的的 2 种方法。

    1.) 如果您的 JSON 符合以下原则:

    { "类型":"文本字段", “特性” : { "属性 1":"值 1", “属性 2”:“值 2”} }

    等等

    您必须有条件代码,具体取决于类型,例如;

    UIControl *newControl
    
    if([[parsedJson valueForKey:@"Type"] isEqualTo:"TextField"])
    {
       newControl = [UITextField alloc]init];
       for(NSDictionary *dict in [parsedJson valueForKey:"Properties")
       {
         [newControl setValue:[dict value] forKey:[dict Key]];
       }
    }
    

    另一方面,如果您的 JSON 使用 UIKit 名称作为类型,例如:

    {"Type":"UITextField","Properties":{"Property1":"Value1","Property2":2}}

    等等

    你可以做一些反射:

    id *control = [[NSClassFromString([parsedJson valueForKey:"Type"]) alloc] init];
    
           for(NSDictionary *dict in [parsedJson valueForKey:"Properties")
           {
             [newControl setValue:[dict value] forKey:[dict Key]];
           }
    

    但您需要进行大量错误处理/try{} catch{},以防系统无法创建类或您为不存在的属性设置值。

    JSON 中声明的属性也需要引用类的属性。

    用于此答案的一些参考资料:

    how to instantiate an object of class from string in Objective-C? - StackOverflow Convert a string (“MyExampleClass”) into a class name (MyExampleClass) - StackOverflow

    【讨论】:

    • 在 iOS 中我们没有复选框控制权如何处理
    • 我没有样品。这一切都是从内存/参考中完成的。选择设置为复选标记的 UITableView 是显示多个选择选项的最佳方式。这也遵循系统用户界面
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多