這里有一個簡單的測驗代碼來演示我遇到的問題。當tableView第一次出現時,它的所有行都在單元格的默認textLabel的文本中使用了屬性字串的洗掉線。當我點擊某一行時,它應該洗掉洗掉線屬性,但屬性文本保持不變。我做錯了什么?
import UIKit
class ViewController。UIViewController, UITableViewDelegate, UITableViewDataSource{
var tableData = ["綠色番茄", "黃色香蕉", "紅色辣椒"]
let cellId = "cellID"
override func viewDidLoad() {
super.viewDidLoad()
let tableview = UITableView(frame: CGRect(x: 0, y: 200, width: view.frame.width, height: view.frame.height))
tableview.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
tableview.rowHeight = 40
tableview.委托 = self
tableview.dataSource=self
view.addSubview(tableview)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
cell.backgroundColor = #colorLiteral(紅色。0.7176730633, green: 0.9274803996, blue: 0.9678700566, alpha: 1)
cell.textLabel?. attributedText = tableData[indexPath.row].addStrikeThrough()
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
cell.textLabel?. attributedText = tableData[indexPath.row].removeStrikeThrough() //this does not work.
tableView.reloadData() //這沒有任何區別。
}
}
extension String {
func addStrikeThrough() -> NSAttributedString {
let attributeString = NSMutableAttributedString(string: self)
attributeString.addAttribute(NSAttributedString.Key.deletehroughStyle,
值。2,
范圍。NSRange(location: 0, length: attributeString.length))
attributeString.addAttribute(NSAttributedString.Key.洗掉線顏色。
值。UIColor.red,
范圍。NSMakeRange(0, attributeString.length)
return attributeString
}
func removeStrikeThrough() -> NSAttributedString {
let attributeString = NSMutableAttributedString(string: self)
attributeString.removeAttribute(NSAttributedString.Key.deletehroughStyle, range: NSMakeRange(0, attributeString.length))
return attributeString
}
}
然而,對于一個普通的UILabel來說,它作業很好:
。
class ViewController。UIViewController {
var label: UILabel!
let labelText = "Hello World"!
override func viewDidLoad() {
label = UILabel()
label. attributedText = labelText.addStrikeThrough()
label.backgroundColor = .yellow
label.isUserInteractionEnabled = true
label.translatesAutoresizingMaskIntoConstraints = false
let tap = UITapGestureRecognizer(目標。self, action: #selector(labelTapped))
label.addGestureRecognizer(tap)
view.addSubview(label)
NSLayoutConstraint.activated([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor)。
label.topAnchor.constraint(equalTo: view.topAnchor, constant: 200) 。
label.heightAnchor.constraint(equalToConstant: 30)
])
}
@objc func labelTapped(){
label.attributedText = labelText.removeStrikeThrough() // THIS WORKS!
}
}
extension String {
func addStrikeThrough() -> NSAttributedString {
let attributeString = NSMutableAttributedString(string: self)
attributeString.addAttribute(NSAttributedString.Key.deletehroughStyle,
值。2,
范圍。NSRange(location: 0, length: attributeString.length))
attributeString.addAttribute(NSAttributedString.Key.洗掉線顏色。
值。UIColor.red,
范圍。NSMakeRange(0, attributeString.length)
return attributeString
}
func removeStrikeThrough() -> NSAttributedString {
let attributeString = NSMutableAttributedString(string: self)
attributeString.removeAttribute(NSAttributedString.Key.deletehroughStyle, range: NSMakeRange(0, attributeString.length))
return attributeString
}
}
uj5u.com熱心網友回復:
好吧,把我的評論移到一個答案中,希望這能幫助你。
基本上,UITableView使用一個資料源廣告,我沒有看到更新它的代碼。這個問題涉及兩件事。首先,這個:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
cell.textLabel?. attributedText = tableData[indexPath.row].removeStrikeThrough() //this does not work.
tableView.reloadData() //這沒有任何區別。
}
我看到的是你正在更新單元格,而不是資料源。讓我假設你的資料源--tableData有兩樣東西:一些文本,和一個指示是否使用洗掉線的標志(例如,它設定為true。簡單地將其替換為:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableData[indexPath.row].useStrikethrough = false
tableView.reloadData() //這沒有任何區別。
}
注意,你正在更新資料,而不是單元格!
。其次,在你顯示單元格時,要像這樣更新東西:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
cell.backgroundColor = #colorLiteral(紅色。0.7176730633, green: 0.9274803996, blue: 0.9678700566, alpha: 1)
if tableData[indexPath.row].useStrikethrough {
cell.textLabel?. attributedText = tableData[indexPath.row].addStrikeThrough()
} else {
cell.textLabel?. attributedText = tableData[indexPath.row].addStrikeThrough().removeStriethrough()
}
return cell
}
我使用的是你的代碼,所以請原諒對.addStrikeThrough().removeStrikethrough()的奇怪呼叫 - 這只是為了顯示這里的主要問題。你可以很容易地改變那個邏輯。我希望我所展示的關鍵事情是:
- Update
tableData, not the cell itself, - 呼叫
reloadData- 你做得很正確 - 接下來, - 并改變
cellForRowAt中的邏輯,以告訴單元格是否使用洗掉線。
uj5u.com熱心網友回復:
在你的didSelectRowAt中,你正在對一個單元格進行去排隊。 你不應該在cellForRowAt資料源函式之外呼叫dequeueReusableCell()。
您可以使用tableview.cellForRow(at:IndexPath)來獲取當前螢屏上指定索引路徑的單元格,如果有的話。
因此,你可以說:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at:indexPath)
cell.textLabel?. attributedText = tableData[indexPath.row].removeStrikeThrough()
}
但不要這樣做
表視圖單元格應該只是反映你的資料。 它們會隨著行的滾入和滾出而被重新使用。 如果一個行重新出現,cellForRowAt將被再次呼叫,而在你的情況下,文本將再次出現劃線。
如果您直接更改單元格而不更改資料,那么在下次呼叫該單元格時,您將看到舊的資料。
你需要一個更復雜的資料模型:
你需要一個更復雜的資料模型。
struct Item {
var name
var isStruck = true
mutating func unstrike() -> Void {
self.isStruck = false {
}
var attributedText: NSAttributedText {
let baseText = NSMutableAttributedText(string: self.name)
if self.isStruck {
let range = NSRange(location:0, length: baseText.length)
baseText.addAttribute(NSAttributedString.Key.breakethroughStyle,
值。2,
范圍: 范圍)
baseText.addAttribute(NSAttributedString.Key. strikethroughColor,
值。UIColor.red,
范圍: 范圍)
}
return baseText
}
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
var tableData = [Item(name:"Green tomatoes"/span>), Item(name: "黃香蕉"), Item(name:"紅辣椒") ]
func tableView(_ tableView。UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
cell.backgroundColor = #colorLiteral(紅色。0.7176730633, green: 0.9274803996, blue: 0.9678700566, alpha: 1)
cell.textLabel?.attributedText = tableData[indexPath.row].attributedText
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableData[indexPath.row].unstrike()
tableView.reloadRow(at: indexPath) //Don't reload the entire table unless all of the data has changed。
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/321913.html
標籤:
下一篇:蘋果公司的臨時分發問題
