动态生成 UITableView 单元格和标题
Dynamically Generate UITableView Cells and Headrs
项目文件:
https://jumpshare.com/v/Otai3BBXYwfvyz8jb53k
(查看这些以查看项目结构是明智的)
问题:
好的,所以我正在关注 tutorial,它创建了一个带有 headers 的 UITableView,然后是单元格内容。
代码有效 运行 很好,现在我想扩展该教程并使用 alamofire 和 Swifty 动态加载该内容JSON。
教程中使用的代码是这样的:
func getSectionsFromData() -> [Sections] {
var sectionsArray = [Sections]()
let animals = Sections(title: "Animals", objects: ["Cats", "Dogs", "Birds", "Lions"])
sectionsArray.append(animals)
return sectionsArray
}
我尝试做的是:
Alamofire.request(.GET, url).validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_, subJson) in json {
for (year, content) in subJson {
let title = year
let objects = content
sectionsArray.append(Sections(title: title, objects: objects))
}
}
}
case .Failure(let error):
print(error)
}
}
如果我打印出它们在控制台中显示的结果 - 所以我知道 JSON 的获取和循环是有效的。然后我添加了
let title = year
let objects = content
sectionsArray.append(Sections(title: title, objects: objects))
但是在这条线上:
sectionsArray.append(Sections(title: title, objects: objects))
我收到这个错误:
cannot convert value of type 'JSON' to expected argument type '[String]'
这是我正在使用的JSON:
{"posts": [
{
"Category1": [
"Post1cat1"
],
"Category2": [
"Post1cat2",
"Post2cat2"
]
}
]}
有人可以帮助我吗? 我可能走错了方向 我想遍历 JSON 并将类别显示为 headers 并将帖子显示在 table.
编辑:2016 年 1 月 29 日
所以,我将循环更改为:
for (_, subJson) in json {
for (index, data) in subJson {
for (title, objects) in data {
sectionsArray.append(Sections(title: title, objects: objects.self.arrayValue.map { [=14=].string!}))
}
}
}
仍然没有运气。当我添加一些打印(在:sectionsArray.append下)以测试是否有数据时:
print("--")
print(title)
print(objects.self.arrayValue.map { [=15=].string!})
print(Sections(title: title, objects: objects.self.arrayValue.map { [=15=].string!}))
我在控制台中得到了这个结果:
--
Category1
["Post1cat1"]
Sections(headings: "Category1", items: ["Post1cat1"])
--
Category2
["Post1cat2", "Post2cat2"]
Sections(headings: "Category2", items: ["Post1cat2", "Post2cat2"])
这表明信息在那里,但是当我 运行 应用程序仍然没有结果时,他 JSON 只有最初定义的部分和上面的单元格。
来自 SwiftyJSON 文档:
for (key,subJson):(String, JSON) in json {
//Do something you want
}
表示subJson是JSON类型。但是,第一个示例中的 Sections 构造函数是:
Sections(title: "Animals", objects: ["Cats", "Dogs", "Birds", "Lions"])
在你的第二个例子中,你称它为:
Sections(title: title, objects: objects)
除非您更改了构造函数,否则它期望 objects
是一个字符串数组,而不是 JSON。这就是为什么您会收到一条错误消息,指出 Swift 无法将 JSON 转换为字符串。在你的例子中, objects
JSON 实际上是一个字符串数组,所以你需要使用类似的东西:
Sections(title: title, objects: objects.arrayValue.map { [=13=].string!})
您的第二个循环在数组对象上,因此在该循环中 year
是索引值,content
是该索引处的对象。
您需要实施一个额外的循环来解决问题,即:
for (_, subJson) in json {
for (index, data) in subJson {
for (title, objects) in data {
sectionsArray.append(Sections(title: title, objects: objects.arrayValue.map { [=10=].string!}))
}
}
}
在第二种解析方法(编辑后)中,您在最后一个循环中迭代数组,因此您可以在那里创建数组并分别添加每个元素,例如:
for (title, data) in subJson {
var elements: [String] = []
for (_, object) in data {
if let stringELement = object.rawString() {
elements.append(stringELement)
}
}
sectionsArray.append(Sections(title: title, objects: elements))
}
或者,如果您愿意,可以使用来自 JSON 对象的转换原始数组,如本例所示:
for (_, subJson) in json["posts"] {
for (title, data) in subJson {
let optionalCastedObjects = data.arrayObject as? [String]
let unwrappedObjects = optionalCastedObjects ?? []
let section = Sections(title: title, objects: unwrappedObjects)
sectionsArray.append(section)
}
}
这应该可以解决提到的编译问题。
但最后请记住,您在同步 getSectionsFromData
方法中使用异步回调(在您的 GET request
中)。在回调 (clojure
) 的值附加新数据之前,您总是会 return 数组。这将导致您永远不会显示以这种方式获取的数据。
更新
为此,您应该重构 getSectionsFromData
方法,如下所示。
func getSectionsFromData(completion: ([Sections]) -> ()) {
var sectionsArray = [Sections]()
Alamofire.request(.GET, url).validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_, subJson) in json["posts"] {
for (title, data) in subJson {
let optionalCastedObjects = data.arrayObject as? [String]
let unwrappedObjects = optionalCastedObjects ?? []
let section = Sections(title: title, objects: unwrappedObjects)
sectionsArray.append(section)
}
}
completion(sectionsArray)
}
case .Failure(let error):
print(error)
}
}
}
以及您的 UITableViewController 中的相关部分class。
var sections: [Sections] = []
override func viewDidLoad() {
super.viewDidLoad()
SectionsData().getSectionsFromData { [weak self](sections: [Sections]) -> () in
self?.sections = sections
self?.tableView.reloadData()
}
}
项目文件:
https://jumpshare.com/v/Otai3BBXYwfvyz8jb53k
(查看这些以查看项目结构是明智的)
问题:
好的,所以我正在关注 tutorial,它创建了一个带有 headers 的 UITableView,然后是单元格内容。
代码有效 运行 很好,现在我想扩展该教程并使用 alamofire 和 Swifty 动态加载该内容JSON。
教程中使用的代码是这样的:
func getSectionsFromData() -> [Sections] {
var sectionsArray = [Sections]()
let animals = Sections(title: "Animals", objects: ["Cats", "Dogs", "Birds", "Lions"])
sectionsArray.append(animals)
return sectionsArray
}
我尝试做的是:
Alamofire.request(.GET, url).validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_, subJson) in json {
for (year, content) in subJson {
let title = year
let objects = content
sectionsArray.append(Sections(title: title, objects: objects))
}
}
}
case .Failure(let error):
print(error)
}
}
如果我打印出它们在控制台中显示的结果 - 所以我知道 JSON 的获取和循环是有效的。然后我添加了
let title = year
let objects = content
sectionsArray.append(Sections(title: title, objects: objects))
但是在这条线上:
sectionsArray.append(Sections(title: title, objects: objects))
我收到这个错误:
cannot convert value of type 'JSON' to expected argument type '[String]'
这是我正在使用的JSON:
{"posts": [
{
"Category1": [
"Post1cat1"
],
"Category2": [
"Post1cat2",
"Post2cat2"
]
}
]}
有人可以帮助我吗? 我可能走错了方向 我想遍历 JSON 并将类别显示为 headers 并将帖子显示在 table.
编辑:2016 年 1 月 29 日
所以,我将循环更改为:
for (_, subJson) in json {
for (index, data) in subJson {
for (title, objects) in data {
sectionsArray.append(Sections(title: title, objects: objects.self.arrayValue.map { [=14=].string!}))
}
}
}
仍然没有运气。当我添加一些打印(在:sectionsArray.append下)以测试是否有数据时:
print("--")
print(title)
print(objects.self.arrayValue.map { [=15=].string!})
print(Sections(title: title, objects: objects.self.arrayValue.map { [=15=].string!}))
我在控制台中得到了这个结果:
--
Category1
["Post1cat1"]
Sections(headings: "Category1", items: ["Post1cat1"])
--
Category2
["Post1cat2", "Post2cat2"]
Sections(headings: "Category2", items: ["Post1cat2", "Post2cat2"])
这表明信息在那里,但是当我 运行 应用程序仍然没有结果时,他 JSON 只有最初定义的部分和上面的单元格。
来自 SwiftyJSON 文档:
for (key,subJson):(String, JSON) in json {
//Do something you want
}
表示subJson是JSON类型。但是,第一个示例中的 Sections 构造函数是:
Sections(title: "Animals", objects: ["Cats", "Dogs", "Birds", "Lions"])
在你的第二个例子中,你称它为:
Sections(title: title, objects: objects)
除非您更改了构造函数,否则它期望 objects
是一个字符串数组,而不是 JSON。这就是为什么您会收到一条错误消息,指出 Swift 无法将 JSON 转换为字符串。在你的例子中, objects
JSON 实际上是一个字符串数组,所以你需要使用类似的东西:
Sections(title: title, objects: objects.arrayValue.map { [=13=].string!})
您的第二个循环在数组对象上,因此在该循环中 year
是索引值,content
是该索引处的对象。
您需要实施一个额外的循环来解决问题,即:
for (_, subJson) in json {
for (index, data) in subJson {
for (title, objects) in data {
sectionsArray.append(Sections(title: title, objects: objects.arrayValue.map { [=10=].string!}))
}
}
}
在第二种解析方法(编辑后)中,您在最后一个循环中迭代数组,因此您可以在那里创建数组并分别添加每个元素,例如:
for (title, data) in subJson {
var elements: [String] = []
for (_, object) in data {
if let stringELement = object.rawString() {
elements.append(stringELement)
}
}
sectionsArray.append(Sections(title: title, objects: elements))
}
或者,如果您愿意,可以使用来自 JSON 对象的转换原始数组,如本例所示:
for (_, subJson) in json["posts"] {
for (title, data) in subJson {
let optionalCastedObjects = data.arrayObject as? [String]
let unwrappedObjects = optionalCastedObjects ?? []
let section = Sections(title: title, objects: unwrappedObjects)
sectionsArray.append(section)
}
}
这应该可以解决提到的编译问题。
但最后请记住,您在同步 getSectionsFromData
方法中使用异步回调(在您的 GET request
中)。在回调 (clojure
) 的值附加新数据之前,您总是会 return 数组。这将导致您永远不会显示以这种方式获取的数据。
更新
为此,您应该重构 getSectionsFromData
方法,如下所示。
func getSectionsFromData(completion: ([Sections]) -> ()) {
var sectionsArray = [Sections]()
Alamofire.request(.GET, url).validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_, subJson) in json["posts"] {
for (title, data) in subJson {
let optionalCastedObjects = data.arrayObject as? [String]
let unwrappedObjects = optionalCastedObjects ?? []
let section = Sections(title: title, objects: unwrappedObjects)
sectionsArray.append(section)
}
}
completion(sectionsArray)
}
case .Failure(let error):
print(error)
}
}
}
以及您的 UITableViewController 中的相关部分class。
var sections: [Sections] = []
override func viewDidLoad() {
super.viewDidLoad()
SectionsData().getSectionsFromData { [weak self](sections: [Sections]) -> () in
self?.sections = sections
self?.tableView.reloadData()
}
}