UITableViewCell 如何知道从数组或字典中加载啥 JSON
Posted
技术标签:
【中文标题】UITableViewCell 如何知道从数组或字典中加载啥 JSON【英文标题】:How can a UITableViewCell know what JSON to load from an Array or DictionariesUITableViewCell 如何知道从数组或字典中加载什么 JSON 【发布时间】:2016-04-22 10:32:12 【问题描述】:假设我有一个包含 3 个 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。
现在我必须为数组中的每个 Dictionary 创建 3 种不同类型的 UITableViewCell。把它想象成一个 Facebook 订阅源,其中每个字典都不同,并且数量不断增长。
我如何告诉每个 Cell 应该加载什么内容?
【问题讨论】:
您的问题最后不清楚,请在您的问题中解释“告诉每个单元格应该加载哪些内容”的确切含义。你想拥有多少个细胞?每本词典 1 个? 这就像 Facebook 或 Instagram 应用程序上的通知选项卡,可能有无限数量的字典(单元格),但每个单元格都有自己的信息,并按每个通知的发出日期排序。跨度> 如果字典是 Demo 类型,我想在 DemoUItableViewCell 中加载该信息,如果字典是 Entry 类型,我想在 EntryUItableViewCell 中加载该信息,依此类推……但在JSON 响应给我的订单。 总是难以理解,但我已经尝试给出答案 【参考方案1】:另一个使用自定义结构作为数据源数组模型的好例子。
首先创建一个enum
以将String
类型映射到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]()
并在解析 JSON 时创建 Item
实例
...
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
代码不是一个完整的工作版本,它只是一个建议如何为不同的类型使用不同的单元格。
【讨论】:
这是一个最适合作为构建基础的框架,非常感谢!我将更新它在完整实施后的样子。 我喜欢您的代码,但我不同意“没有初始值的声明”,如果您的数据可以由 NSCoder 处理,您可能会遇到一些问题.. @AlessandroOrnano 如前所述,这是一个建议。但是没有初始值的声明仅意味着使用所需的成员初始化器将可靠地初始化公共变量的所有值,因为它们是非可选的。【参考方案2】:使用这些方法:
// 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
【讨论】:
感谢您的回复,当您知道回复的确切数量以及每个回复必须在该部分中的位置时,这将很有效。将我的示例想象为 Facebook 提要,其中每个帖子都不同,您需要确定 Cell 需要加载的内容。【参考方案3】:我认为您可以尝试自定义数据源,创建一个类(内部类或非内部类),例如:
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)
【讨论】:
以上是关于UITableViewCell 如何知道从数组或字典中加载啥 JSON的主要内容,如果未能解决你的问题,请参考以下文章
编辑完成后如何从自定义uitableviewcell的文本字段向数组添加数据
多个 UITableViewCell 中的多个数组 [关闭]
设置从 HTML 字符串生成的 UITableViewCell 标签
Swift - 如何将数据从 UITableViewCell 类传递到 UIViewController