如果可用,将项目添加到特定 Table 视图行
Add Item to Specific Table View Row if Available
我正在尝试从我的 Parse 数据库创建一个用户表视图,这些用户在同一个 class(在学校)。所有用户都必须有用户名,但并非所有人都会为应用提供全名或设置个人资料图片。我使用此代码:
let studentsQuery = PFQuery(className:"_User")
studentsQuery.whereKey("objectId", containedIn: studentsArray! as! [AnyObject])
let query2 = PFQuery.orQueryWithSubqueries([studentsQuery])
query2.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
if error != nil {
// Display error in tableview
} else if results! == [] {
spinningActivity.hideAnimated(true)
print("error")
} else if results! != [] {
if let objects = results {
for object in objects {
if object.objectForKey("full_name") != nil {
let studentName = object.objectForKey("full_name")! as! String
self.studentNameResults.append(studentName)
}
if object.objectForKey("username") != nil {
let studentUsername = object.objectForKey("username")! as! String
self.studentUsernameResults.append(studentUsername)
}
if object.objectForKey("profile_picture") != nil {
let studentProfilePictureFile = object.objectForKey("profile_picture") as! PFFile
studentProfilePictureFile.getDataInBackgroundWithBlock({ (image: NSData?, error: NSError?) in
if error == nil {
let studentProfilePicture : UIImage = UIImage(data: image!)!
self.studentProfilePictureResults.append(studentProfilePicture)
} else {
print("Can't get profile picture")
// Can't get profile picture
}
self.studentsTableView.reloadData()
})
spinningActivity.hideAnimated(true)
} else {
// no image
}
}
}
} else {
spinningActivity.hideAnimated(true)
print("error")
}
}
如果所有用户都有用户名 full_name 和 profile_picture,则此代码可以正常工作。但是,我无法弄清楚如何获取用户用户名的 tableView
并仅当用户有图片时才将用户名或图片添加到用户对应的 tableViewCell
中。这是我的 tableView
的配置方式:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return studentUsernameResults.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("studentsCell", forIndexPath: indexPath) as! StudentsInClassInformationTableViewCell
cell.studentProfilePictureImageView.layer.cornerRadius = cell.studentProfilePictureImageView.frame.size.width / 2
cell.studentProfilePictureImageView.clipsToBounds = true
cell.studentProfilePictureImageView.image = studentProfilePictureResults[indexPath.row]
cell.studentUsernameLabel.text = studentUsernameResults[indexPath.row]
cell.studentNameLabel.text = studentNameResults[indexPath.row]
return cell
}
studentProfilePictureResults
、studentUsernameResults
和 studentNameResults
来自从 Parse 中提取的用户图片、用户名和姓名结果的数组。如果用户没有个人资料照片,我会收到错误 Index is out of range
。显然,这意味着有,比如说,三个名字,三个用户名,只有两张图片,Xcode 不知道如何配置单元格。我的问题:如何设置一个包含用户用户名的 tableView 并将他们的姓名和个人资料图片放在同一个单元格中,前提是他们有一个?
尝试将不同的属性存储在不同的数组中将是一个问题,因为正如您所发现的,您最终会遇到特定用户没有属性的问题。您可以使用一个可选数组,这样您就可以为不存在的属性存储 nil
,但是将 PFObject
本身存储在一个数组中并访问 [=13= 中的属性要简单得多] 而不是拆分属性。
由于获取照片需要单独的异步操作,因此您可以单独存储它。与其使用数组来存储检索到的照片,这会遇到同样的排序问题,不如使用字典,由用户 ID 索引;尽管对于大量学生来说,使用 SDWebImage
之类的工具来下载 cellForRowAtIndexPath
.
中要求的照片可能会更有效率
// these are instance properties defined at the top of your class
var students: [PFObject]?
var studentPhotos=[String:UIImage]()
// This is in your fetch function
let studentsQuery = PFUser.Query()
studentsQuery.whereKey("objectId", containedIn: studentsArray! as! [AnyObject])
let query2 = PFQuery.orQueryWithSubqueries([studentsQuery])
query2.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
guard (error == nil) else {
print(error)
spinningActivity.hideAnimated(true)
return
}
if let results = results {
self.students = results
for object in results {
if let studentProfilePictureFile = object.objectForKey("profile_picture") as? PFFile {
studentProfilePictureFile.getDataInBackgroundWithBlock({ (image: NSData?, error: NSError?) in
guard (error != nil) else {
print("Can't get profile picture: \(error)")
return
}
if let studentProfilePicture = UIImage(data: image!) {
self.studentPhotos[object["username"]!]=studentProfilePicture
}
}
}
spinningActivity.hideAnimated(true)
self.tableview.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.students != nil {
return self.students!.count
}
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("studentsCell", forIndexPath: indexPath) as! StudentsInClassInformationTableViewCell
cell.studentProfilePictureImageView.layer.cornerRadius = cell.studentProfilePictureImageView.frame.size.width / 2
cell.studentProfilePictureImageView.clipsToBounds = true
let student = self.students[indexPath.row]
if let studentPhoto = self.studentPhotos[student["username"]!] {
cell.studentProfilePictureImageView.image = studentProfilePictureResults[indexPath.row]
} else {
cell.studentProfilePictureImageView.image = nil
}
cell.studentUsernameLabel.text = student["username"]!
if let fullName = student["full_name"] {
cell.studentNameLabel.text = fullName
} else {
cell.studentNameLabel.text = ""
return cell
}
其他一些提示;
- 在 iOS 世界中并没有真正使用 _ 来分隔字段名称中的单词;驼峰式是首选,所以
fullName
而不是 full_name
- 如果您有一个
class
字段或引用对象,那么您的 Parse 查询看起来会更有效率,这样您就不需要提供其他 class 成员的数组。
我正在尝试从我的 Parse 数据库创建一个用户表视图,这些用户在同一个 class(在学校)。所有用户都必须有用户名,但并非所有人都会为应用提供全名或设置个人资料图片。我使用此代码:
let studentsQuery = PFQuery(className:"_User")
studentsQuery.whereKey("objectId", containedIn: studentsArray! as! [AnyObject])
let query2 = PFQuery.orQueryWithSubqueries([studentsQuery])
query2.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
if error != nil {
// Display error in tableview
} else if results! == [] {
spinningActivity.hideAnimated(true)
print("error")
} else if results! != [] {
if let objects = results {
for object in objects {
if object.objectForKey("full_name") != nil {
let studentName = object.objectForKey("full_name")! as! String
self.studentNameResults.append(studentName)
}
if object.objectForKey("username") != nil {
let studentUsername = object.objectForKey("username")! as! String
self.studentUsernameResults.append(studentUsername)
}
if object.objectForKey("profile_picture") != nil {
let studentProfilePictureFile = object.objectForKey("profile_picture") as! PFFile
studentProfilePictureFile.getDataInBackgroundWithBlock({ (image: NSData?, error: NSError?) in
if error == nil {
let studentProfilePicture : UIImage = UIImage(data: image!)!
self.studentProfilePictureResults.append(studentProfilePicture)
} else {
print("Can't get profile picture")
// Can't get profile picture
}
self.studentsTableView.reloadData()
})
spinningActivity.hideAnimated(true)
} else {
// no image
}
}
}
} else {
spinningActivity.hideAnimated(true)
print("error")
}
}
如果所有用户都有用户名 full_name 和 profile_picture,则此代码可以正常工作。但是,我无法弄清楚如何获取用户用户名的 tableView
并仅当用户有图片时才将用户名或图片添加到用户对应的 tableViewCell
中。这是我的 tableView
的配置方式:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return studentUsernameResults.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("studentsCell", forIndexPath: indexPath) as! StudentsInClassInformationTableViewCell
cell.studentProfilePictureImageView.layer.cornerRadius = cell.studentProfilePictureImageView.frame.size.width / 2
cell.studentProfilePictureImageView.clipsToBounds = true
cell.studentProfilePictureImageView.image = studentProfilePictureResults[indexPath.row]
cell.studentUsernameLabel.text = studentUsernameResults[indexPath.row]
cell.studentNameLabel.text = studentNameResults[indexPath.row]
return cell
}
studentProfilePictureResults
、studentUsernameResults
和 studentNameResults
来自从 Parse 中提取的用户图片、用户名和姓名结果的数组。如果用户没有个人资料照片,我会收到错误 Index is out of range
。显然,这意味着有,比如说,三个名字,三个用户名,只有两张图片,Xcode 不知道如何配置单元格。我的问题:如何设置一个包含用户用户名的 tableView 并将他们的姓名和个人资料图片放在同一个单元格中,前提是他们有一个?
尝试将不同的属性存储在不同的数组中将是一个问题,因为正如您所发现的,您最终会遇到特定用户没有属性的问题。您可以使用一个可选数组,这样您就可以为不存在的属性存储 nil
,但是将 PFObject
本身存储在一个数组中并访问 [=13= 中的属性要简单得多] 而不是拆分属性。
由于获取照片需要单独的异步操作,因此您可以单独存储它。与其使用数组来存储检索到的照片,这会遇到同样的排序问题,不如使用字典,由用户 ID 索引;尽管对于大量学生来说,使用 SDWebImage
之类的工具来下载 cellForRowAtIndexPath
.
// these are instance properties defined at the top of your class
var students: [PFObject]?
var studentPhotos=[String:UIImage]()
// This is in your fetch function
let studentsQuery = PFUser.Query()
studentsQuery.whereKey("objectId", containedIn: studentsArray! as! [AnyObject])
let query2 = PFQuery.orQueryWithSubqueries([studentsQuery])
query2.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
guard (error == nil) else {
print(error)
spinningActivity.hideAnimated(true)
return
}
if let results = results {
self.students = results
for object in results {
if let studentProfilePictureFile = object.objectForKey("profile_picture") as? PFFile {
studentProfilePictureFile.getDataInBackgroundWithBlock({ (image: NSData?, error: NSError?) in
guard (error != nil) else {
print("Can't get profile picture: \(error)")
return
}
if let studentProfilePicture = UIImage(data: image!) {
self.studentPhotos[object["username"]!]=studentProfilePicture
}
}
}
spinningActivity.hideAnimated(true)
self.tableview.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.students != nil {
return self.students!.count
}
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("studentsCell", forIndexPath: indexPath) as! StudentsInClassInformationTableViewCell
cell.studentProfilePictureImageView.layer.cornerRadius = cell.studentProfilePictureImageView.frame.size.width / 2
cell.studentProfilePictureImageView.clipsToBounds = true
let student = self.students[indexPath.row]
if let studentPhoto = self.studentPhotos[student["username"]!] {
cell.studentProfilePictureImageView.image = studentProfilePictureResults[indexPath.row]
} else {
cell.studentProfilePictureImageView.image = nil
}
cell.studentUsernameLabel.text = student["username"]!
if let fullName = student["full_name"] {
cell.studentNameLabel.text = fullName
} else {
cell.studentNameLabel.text = ""
return cell
}
其他一些提示;
- 在 iOS 世界中并没有真正使用 _ 来分隔字段名称中的单词;驼峰式是首选,所以
fullName
而不是full_name
- 如果您有一个
class
字段或引用对象,那么您的 Parse 查询看起来会更有效率,这样您就不需要提供其他 class 成员的数组。