2016-04-22 30 views
0

假设我有一个JSON数组的3个字典,每个字典都有自己的类型(demo,entry,comment)。UITableViewCell如何知道从数组或字典中加载的JSON

[ 
{ 
    "_id": "random ID", 
    "profile": "random ID Profile", 
    "demo": { 
     "_id": "random ID", 
     "profile": { 
      "_id": "random ID", 
      "name": "name", 
      "username": "username", 
      "description": "description", 
      "picture": "/picture" 
     }, 
     "path": "/path", 
     "created": "date" 
    }, 
    "type": "demo", 
    "source": "570aa8f647a70780a7111e91", 
    "__v": 0, 
    "created": "date" 
}, 
{ 
    "_id": "random ID", 
    "comment": "random comment ID", 
    "type": "comment", 
    "source": "57077c4e356c10371ca91ad9", 
    "__v": 0, 
    "created": "date" 
}, 
{ 
    "_id": "random ID", 
    "entry": "random entry ID", 
    "type": "entry", 
    "source": "57077c4e356c10371ca91ad9", 
    "__v": 0, 
    "created": "date" 
} 
] 

现在我正在检查请求中的类型,因此我只获得演示。

func getTimeline(urlString: NSURL, completion: ([ModelDemos]) -> Void) { 
    Alamofire.request(.GET, urlString).responseJSON { response in 

     if let httpResponse = response.response { 
      switch httpResponse.statusCode { 
      case 200: 
       var modelTimeline = [ModelDemos]() 

       if let demos = response.result.value as? [JSONDictionary] { 
        for demo in demos { 
         if let type = demo["type"] as? String { 
          if type == "demo" { 
           if let demo = demo["demo"] as? JSONDictionary { 
            let JSON = ModelDemos(data: demo) 
            modelTimeline.append(JSON) 
           } 
          } 
         } 
        } 
       } else { print("not working") } 

       dispatch_async(dispatch_get_main_queue()) { 
        completion(modelTimeline) 
        print("Am I back on the main thread ? Response: \(NSThread.isMainThread())") 
       } 
      default: 
       return 
      } 
     } 
    } 
} 

这在我TimelineViewController设置完成方法后

var timelineDemos = [ModelDemos]() 

func runApiManagerTimeline() { 
    guard let urlString = urlString else {return} 
    apiManagerCurrentUserProfile.getTimeline(urlString, completion: didGetCurrentUserProfileDemos) 
} 

func didGetCurrentUserProfileDemos(demos: [ModelDemos]) { 
    timelineDemos = demos 
    timelineCollectionView.reloadData() 
} 

一切工作正常,我只得到了演示词典,我可以将其加载到DemoUITableViewCell。

现在我必须为数组中的每个字典创建3种不同类型的UITableViewCell。将它想象成Facebook供稿,其中每个词典不同,并且数量不断增长。

我该如何告诉每个Cell它应该加载哪些内容?

+0

你的问题最后没有明确说明,请在你的问题中解释一下你的意思是“告诉每个单元格应该加载哪些内容”。你想拥有多少个细胞? 1字典? –

+0

这就像Facebook或Instagram应用程序中的通知标签,可能有无限数量的字典(单元格),但每个单元格都有它自己的信息,并按每个通知发布日期排序。 –

+0

如果字典是一种演示,我想在DemoUItableViewCell中加载这些信息,如果字典的类型为Entry,我想在EntryUItableViewCell中加载这些信息,依此类推......但按照给我的顺序JSON响应。 –

回答

0

又一个很好的例子,使用自定义的结构作为模型数据源阵列。

首先创建一个enumString类型映射到enum案件

enum DataType : String { case Demo = "demo", Comment = "comment", Entry = "entry" } 

创建自定义struct项目作为数据源模型。声明三种数据类型的所有公共属性不带初始值,单个属性初始值使用隐式成员初始化程序创建Item实例并根据类型将值分配给各个属性。样品性质与JSON和仅作为示例

struct Item { 
    // common properties 
    var type : DataType 
    var source : String 
    var created : String 

    // individual properties 
    var username = "" 
    var description = "" 
    var picture = "" 
} 

在TableView中控制器创建数据源阵列

var modelTimeline = [Item]() 

并创建Item实例在解析JSON

... 
if let demos = response.result.value as? [JSONDictionary] { 
    for demo in demos { 
    if let type = demo["type"] as? String { 
     let source = type["source"] ?? "" 
     let created = type["date"] ?? "" 
     var item = Item(type: DataType(rawValue:type), source: source, created: created) 
     if type == "demo" { 
     if let demo = demo["demo"] as? JSONDictionary, profile = demo["profile"] as? JSONDictionary { 
      item.username = profile["username"] ?? "" 
      item.description = profile["description"] ?? "" 
      item.picture = profile["picture"] ?? "" 
     } 
     } 
     modelTimeline.append(item) 
    } 
    } 
} else { print("not working") } 
... 

cellForRowAtIndexPath根据类型创建单元格并将值分配给UI元素

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let item = modelTimeline[indexPath.row] 
    switch item.type { 
    case .Demo: 
    let cell = tableView.dequeueReusableCellWithIdentifier("DemoCell", forIndexPath: indexPath) as! DemoUItableViewCell 
    cell.usernameLabel.text = item.username 
    cell.descriptionLabel.text = item.description 
    cell.sourceLabel.text = item.source 
    // populate other UI elements 
    return cell 

    case .Comment: 
    cell = tableView.dequeueReusableCellWithIdentifier("CommentCell", forIndexPath: indexPath) as! CommentUItableViewCell 
    cell.sourceLabel.text = item.source 
    // populate other UI elements 
    return cell 

    case .Entry: 
    cell = tableView.dequeueReusableCellWithIdentifier("EntryCell", forIndexPath: indexPath) as! EntryUItableViewCell 
    cell.sourceLabel.text = item.source 
    // populate other UI elements 
    return cell 
    } 
} 

该代码不是一个完整的工作版本,它只是一个建议如何使用不同类型的不同单元格。

+0

这个解决方案最好作为一个框架来构建,非常感谢!我将在完整实施后更新它的外观。 –

+0

我喜欢你的代码,但林不同意“声明没有初始值”,如果你的数据可以通过NSCoder处理,你可以有一些问题。 –

+0

@AlessandroOrnano如上所述,这是一个建议。但是*没有初始值的声明*仅意味着使用所需的成员初始化器将可靠地初始化所有公共变量的值,因为它们是非可选项。 – vadian

0

有了这些方法:

// MARK: - Table view Functions 
override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    //3 because of 3 different dictionaries 
    return 3 
} 

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
//Define the amount of rows for each section 
    if (section == 0) { 
     return --amount of entries in regarding dictionary-- 
    } else if (section == 1) { 
     return --amount of entries in regarding dictionary-- 
    } else { 
     return --amount of entries in regarding dictionary-- 
    } 
} 

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
if (indexPath.section == 0) { 
     //Dict 1 
} else if (indexPath.section == 1) { 
     //Dict 2 
} else { 
     //Dict 3 
} 
+0

感谢您的回复,当您知道确切的回复数量以及每个回复必须位于该部分中的情况时,这种方式会很有效。想象一下我的例子,作为一个Facebook feed,每个帖子都不同,你需要确定Cell需要加载的内容。 –

+0

好吧,然后我把你的问题弄错了。对不起 – glace

0

我想你可以尝试像定制您的数据源制作类(内部类与否):

class GeneralNotificationInfo: NSObject { 
    var notificationTime:NSDate! = NSDate() 
    enum notificationType: Int { 
     case Demo = 1 
     case Entry = 2 
     case Test = 3 
    } 
    var data:NSDictionary! = NSDictionary() 
    ... 
} 

有了这个个性化,你可以轻松地处理你的细胞。

关于你的代码:

typealias AlamoNetSuccess = (result: NSDictionary?) -> Void 
typealias AlamoNetProgress = (result: NSDictionary?) -> Void 
typealias AlamoNetFailure = (error: NSDictionary?) -> Void 

var params :[String: AnyObject]? = ["user": "David", "age": 40] 

func getTimeline(urlString: NSURL,params: [String: AnyObject], success successBlock :AlamoNetSuccess, 
     failure failureBlock :AlamoNetFailure) { 
.request(.GET, url, parameters: params, encoding: ParameterEncoding.URL) 
      .responseJSON { response in 
       print("∙ ---") 
       print("∙ Net URLs: \(response.request?.URL)") // original URL request 
       print("∙ ---") 
       //print(response.response) // URL response 
       //print(response.data)  // server data 
       //print(response.result) // result of response serialization 
       if response.result.isSuccess { 
        let jsonDic = response.result.value as! NSDictionary 
        successBlock(result: jsonDic) 
       } else { 
        let httpError: NSError = response.result.error! 
        let statusCode = httpError.code 
        let error:NSDictionary = ["error" : httpError,"statusCode" : statusCode] 
         failureBlock(error: error) 
       } 
} 

let wrappedNetSuccess: AlamoNetSuccess = {(result: NSDictionary?) -> Void in // 
    print ("∙ Net Success: \(result)") 
    // do whatever you want with your dictionary, parse it into datasource... 
} 

let wrappedAPIFailure: AlamoNetFailure = {(error: NSDictionary?) -> Void in 
    print ("∙ Net Failure: \(error)") 
    // handle your network error with alertViews or other.. 
} 

apiManagerCurrentUserProfile.getTimeline(urlString,params:[], success: wrappedAPISuccess, failure: wrappedAPIFailure)