我有一个UIViewController,当用户点击一个按钮时,我想显示一个UITableView。我从服务器收到数据。
问题在于发生了一些奇怪的事情。有时,并非所有单元格都会更新。换句话说,在我的原型单元格中,有两个按钮,默认文本,但是当我从服务器加载数据时,不是所有按钮文本都更新,而是当我滚动表格时,它们变为更新。 同样当我滚动*表格时,有时按钮会返回默认文字。
以下是我的代码:(非常简单)
class CusinePreferencesTableView: NSObject, UITableViewDelegate, UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentefiers.oneCusinePreferencesCell.rawValue, forIndexPath: indexPath) as! OneCusinePreferencesTableViewCell
var row = indexPath.row
print("row = \(row)")
let oneCusineDataLeft = Preferences2ViewController.cusines![row]
cell.leftButton.titleLabel?.text = oneCusineDataLeft
row = row + 1
if row < Preferences2ViewController.cusines!.count{
let oneCusineDataRight = Preferences2ViewController.cusines![row]
cell.rightButton.titleLabel?.text = oneCusineDataRight
}else {
//I should hide the right button
}
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let cusines = Preferences2ViewController.cusines {
if cusines.count % 2 == 0 {
return cusines.count/2
}else {
var count = cusines.count/2
count = count + 1
return count
}
}else {
return 0
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
}
如果您发现自己没有得到问题描述,我可以为您制作视频
我已经调用了reloadData,就像你在这里看到的那样(我从服务器获取数据)
func loadCusiens(){
let url = NSURL(string: ConstantData.getWebserviceFullAddress()+"preferences/cusines")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error ) in
if let error = error {
print("error = \(error)")
}
if let data = data {
do{
let jsonArray = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! NSArray
var results = [String]()
for oneJSON in jsonArray {
let name = oneJSON["name"] as! String
results.append(name)
}
dispatch_async(dispatch_get_main_queue(), {
Preferences2ViewController.cusines = results
self.cusineTableView.reloadData()
})
} catch{
print("This exception happened = \(error)")
}
}
})
task.resume()
}
现在在else部分,我将右键的文本设置为&#34; sometext&#34; 这是关于问题的视频
答案 0 :(得分:1)
看起来像是重用问题。基本上,如果您按照Apple和其他地方的示例进行操作,它会使用出列函数。这意味着iOS将查找已经不再显示的现有单元格,并为您提供绘制新单元格内容的单元格。但是当然如果旧电池有一堆东西,你会看到旧的东西。解决方案是始终将所有内容分配给正确的新值。
如果您的单元格具有可变信息,这可以让您轻松获得,例如,如果某个条目设置了您设置的图片,但是如果它没有,则不会设置。然后会发生什么事情,当你得到一个没有图片的条目时你的代码可能没有将图像设置为nil,你就会看到一个滚动的旧单元格的图片。
答案 1 :(得分:1)
请让我解释一下UITableViewCells
作品的重复使用
假设你有一个非常庞大的细胞,你只能在屏幕上看到3个细胞。 现在假设您在屏幕上看到以下单元格:
A
B
C
在屏幕上......您的数据源为:A
B
C
C
B
A
。
现在你正在向下滚动1个单元格:
因此,单元格A
从Up(它是第一个单元格)向下并成为您最后一个可见单元格
所以现在在屏幕上你会看到
B
C
A // While you want to draw a cell `C` here according to the dataSource
cellForRowAtIndexPath...
您从头开始获得相同的单元格A
。
假设您的单元格A
只有1个按钮,而单元格C
需要显示2个按钮
因为您已经绘制了单元格A
,所以您使用1个按钮绘制它(假设您将右侧按钮隐藏属性设置为YES
)。
现在你想在重用的单元格C
上绘制单元格A
(假设你为细胞类型设置了TAGS,以便知道在cellForRowAtIndexPath
中弹出了哪种类型的细胞)
现在您可以查询单元格的标签
if(myCell.tag == `A`/*(Assume you have an Enum for tags)*/)
{
//So here you will want to Unhide the Right button of the cell (which is currently still cell A
//After you have done with all needed adjustments you will want to set the appropriate tag for this cell to be ready for the next reuse -> so set it's tag to C
//Now next time this cell will get reused it will be drawn as cell `C` and it will think it is a cell `C`
}
答案 2 :(得分:1)
<强>更新强>
主要问题不是单元重用,也不是我在下面解释的布局问题,而是使用:
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/HeyVolo.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="@color/darkblue"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/main.backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
android:src="@drawable/peace"
app:layout_collapseMode="parallax"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:id="@+id/eventDescriptionText"
android:text="" />
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_assignment_turned_in_24dp"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end" />
设置按钮文字。你必须使用:
cell.leftButton.titleLabel?.text = oneCusineDataLeft
代替。 (实质上,cell.leftButton.setTitle(oneCusineDataLeft, forState: .Normal)
会跟踪标题文本在处于不同的状态时应显示的状态&#34; - 正常,选定等。虽然您的代码更改了当前显示的文本,一旦按钮改变状态,它就会将文本设置回存储的值。我假设按钮状态在显示单元格时被重置。UIButton
方法更新存储的值。)
<强>原始强>
抛开细胞重用问题,我不认为你的代码会达到你想要的效果。按照目前的编码,布局将是这样的:
setTitle
我猜你真的想要这个:
Row 0: left: cuisine 0, right: cuisine 1
Row 1: left: cuisine 1, right: cuisine 2
Row 2: left: cuisine 2, right: cuisine 3
如果是这种情况,请按如下方式修改您的代码:
Row 0: left: cuisine 0, right: cuisine 1
Row 1: left: cuisine 2, right: cuisine 3
Row 2: left: cuisine 4, right: cuisine 5
我还应该注意,使用func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentefiers.oneCusinePreferencesCell.rawValue, forIndexPath: indexPath) as! OneCusinePreferencesTableViewCell
var row = indexPath.row
print("row = \(row)")
let oneCusineDataLeft = Preferences2ViewController.cusines![2*row]
cell.leftButton.titleLabel?.text = oneCusineDataLeft
if (2*row+1) < Preferences2ViewController.cusines!.count{
let oneCusineDataRight = Preferences2ViewController.cusines![2*row+1]
cell.rightButton.titleLabel?.text = oneCusineDataRight
}else {
//I should hide the right button
cell.rightButton.titleLabel?.text = ""
}
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let cusines = Preferences2ViewController.cusines {
if cusines.count % 2 == 0 {
return cusines.count/2
}else {
return (cusines.count+1)/2
}
}else {
return 0
}
}
而不是UICollectionView
可能会更好,因为前者将更容易和直观地提供多列流。