【发布时间】:2015-12-24 16:40:35
【问题描述】:
我正在尝试在我的 UIViewController 子类中的 UITableView 中显示新闻文章(我需要其中的一些其他视图,这就是我不使用 UITableViewController 的原因)
单元格应该是全宽和自动高度。
问题是可见单元格在第一次加载时没有正确的高度,因此它们根本无法正确显示,它们只有在我向下滚动后才变得正确大小(其他已经正确大小的单元格是) 并备份。
我尝试向 UITableView 和单元格添加 setNeedsUpdateConstraints、updateConstraints、layoutSubviews、layoutIfNeeded 和其他类似方法的各种组合,但它根本没有任何效果。
我非常感谢任何帮助,因为我已经尝试解决这个问题很长时间了,但从未想出解决方案。
我的设置
我有 MyStoryCell 类型的自定义单元格,它存储在 .xib 文件中:
MyStoryCell.xib in Interface Builder
它的类如下所示:
class MyStoryCell: UITableViewCell
{
// MARK: - Properties
@IBOutlet weak var badgeView: UIImageView!
@IBOutlet weak var thumbnailView: UIImageView!
@IBOutlet weak var dateLabel: UILabel!
@IBOutlet weak var taglineLabel: UILabel!
@IBOutlet weak var titleLabel: UILabel!
// MARK: - Methods
func setTaglineText(text: String)
{
....
}
func setTitleText(text: String)
{
...
}
// MARK: - Overrides
override func awakeFromNib() {
super.awakeFromNib()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func layoutSubviews() {
super.layoutSubviews()
if let image = self.thumbnailView?.image
{
// Using PureLayout
self.thumbnailView?.autoSetDimension(.Height, toSize: (self.contentView.frame.width * image.size.height / image.size.width))
}
}
}
视图控制器(函数fetchTableData)从网络上拉取一些文章,将它们存储在一个数组中(currentStories),然后将它们全部添加到 UITableView 使用:
self.table.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
在视图控制器的 viewDidLoad 覆盖我有:
override func viewDidLoad()
{
super.viewDidLoad()
// Setting up table view
table.delegate = self
table.dataSource = self
table.registerNib(UINib(nibName: "MyStoryCell", bundle: nil), forCellReuseIdentifier: "StoryCell")
// Setting cells to automatic height
table.estimatedRowHeight = 300
table.rowHeight = UITableViewAutomaticDimension
// ... some more code
fetchTableData()
}
我的表格视图功能是:
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return currentStories.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell: MyStoryCell? = tableView.dequeueReusableCellWithIdentifier("StoryCell", forIndexPath: indexPath) as? MyStoryCell
if cell == nil
{
tableView.registerNib(UINib(nibName: "MyStoryCell", bundle: nil), forCellReuseIdentifier: "StoryCell")
cell = tableView.dequeueReusableCellWithIdentifier("StoryCell", forIndexPath: indexPath) as? MyStoryCell
}
if currentStories.count >= indexPath.row + 1
{
let currentStory: Story = currentStories[indexPath.row]
dispatch_async(get_user_queue()) {
let badgeImage = codeToFetchBadgeImage
dispatch_async(dispatch_get_main_queue(), {
cell?.badgeView.image = badgeImage
})
let thumbnailImage = codeToFetchThumbnailImage
dispatch_async(dispatch_get_main_queue(), {
cell?.thumbnailView.image = thumbnailImage
})
}
// Set labels
cell?.dateLabel.text = currentStory.storyDate
cell?.setTitleText(currentStory.storyTitle) // Attributed string
cell?.setTaglineText(currentStory.storyTagline) // Attributed string
}
return cell!
}
fetchTableData 实现:
func fetchTableData()
{
/* removed unnecessary code for displaying loading indicator etc. */
stories = [Story]()
currentStories = [Story]()
table.reloadData()
// Go through all the feeds
for feed in 0...rss_urls.count-1
{
// Set url of the RSS feed
var rss_url: NSURL = rss_urls[feed]
// Try to download the RSS feed
if var rss_data: NSData = NSData(contentsOfURL: rss_url)
{
// Initialize the XML Parser and set its delegate to self
parser = NSXMLParser(data: rss_data)
parser.delegate = self
// Start parsing XML
parser.parse()
}
else
{
alert_rss_error_show()
}
}
// Sort by ID
stories.sort{ $0.storyId.toInt() > $1.storyId.toInt() }
}
class DataManager {
func requestData(offset:Int, size:Int, array:[Story], listener:([Story]) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
//generate items
var arr:[Story] = []
var limit = offset + size
if limit >= stories.count
{
limit = stories.count - 1
}
if offset > limit
{
allLoaded = true
return
}
// For each story
for i in offset...limit {
// Story for current index
var currentStory: Story = stories[i]
if let badgeUrl = currentStory.storyBadgeUrl
{
if !badgeUrl.isEmpty
{
if let currentBadge = badgeCache[badgeUrl] { }
else
{
if let badgeData = NSData(contentsOfURL: NSURL(string: badgeUrl)!)
{
var image = UIImage(data: badgeData)
badgeCache[badgeUrl] = image
}
}
}
}
// If story has a thumbnail stored in cache, skip the next step
if let currentThumbnail = thumbnailCache[currentStory.storyLink] { }
else if !currentStory.storyThumbLink.isEmpty
{
if let thumbnailData = NSData(contentsOfURL: NSURL(string: currentStory.storyThumbLink)!)
{
var image = UIImage(data: thumbnailData)
thumbnailCache[currentStory.storyLink] = image
}
}
arr.append(currentStory)
}
//call listener in main thread
dispatch_async(dispatch_get_main_queue()) {
listener(arr)
}
}
}
loadSegment(0, size: PageSize)
}
func loadSegment(offset:Int, size:Int) {
if (!self.isLoading) {
self.isLoading = true
let manager = DataManager()
manager.requestData(offset, size: size, array: currentStories,
listener: {(items:[Story]) -> () in
for item in items {
var row = currentStories.count
var indexPath = NSIndexPath(forRow:row,inSection:0)
currentStories.append(item)
self.table.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
self.isLoading = false
}
)
}
}
【问题讨论】:
-
你能展示一下 fetchTableData() 的实现吗?
-
@GaneshKamath 按要求添加了它
-
酷,Jan Bureš。您是否尝试在 viewWillAppear 中调用 reloadData?
-
@GaneshKamath 我做了,但没有任何改变。我认为问题在于缩略图是异步加载的,但不知道如何解决这个问题
-
是的。如果您提取的数据中有图像尺寸(或纵横比)以显示在表格中,则可以解决此问题。
标签: ios iphone swift uitableview autolayout