Я протестировал модуль readMoreTextView
Ильи Пучки и на статическом тексте внутри проекта все работает. но я пытаюсь это с текстом, который приходит от API конца.
Ошибка : ячейка не развернется полностью, чтобы раскрыть весь текст. Он покажет примерно половину высоты следующей строки ... это означает, что если текст имеет высоту 14 пикселей, то опция ЧИТАТЬ БОЛЬШЕ будет отображать только верхнюю половину текста.
Если я отключу опции readmoretext
и использую textView
в качестве простого textView
, тогда textview
будет отображать весь текст, ... пока я не прокручиваю.
при прокрутке я теряю около 12 строк текста в одном сообщении.
Является ли textView
просто плохим для одиночных струн из бэкэнда?
так что это говорит мне о проблеме tableView.reloadData()
или GCD
. Но я потерялся, я не знаю, где попробовать. проверить любой из вариантов.
Я смешиваю две капсулы, AzureBot
и ReadMoreTextView
. строка / текст поступает от лазурного бота, а затем загружается в текстовое представление.
Теперь я понимаю, что сосу такую простую задачу.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let message = self.messages[indexPath.row]
let sending = message.from?.id == BotClient.shared.currentUser.id
switch sending {
case true:
let cell = tableView.dequeueReusableCell(withIdentifier: "UserTableViewCell", for: indexPath) as! UserTableViewCell
cell.transform = tableView.transform
cell.messageLabel.text = message.text
return cell
case false:
let cell = tableView.dequeueReusableCell(withIdentifier: "BotTableCell", for: indexPath) as! BotTableCell
cell.botMessage.text = message.text
cell.botMessage.shouldTrim = !expandedCells.contains(indexPath.row)
cell.botMessage.setNeedsUpdateTrim()
cell.botMessage.layoutIfNeeded()
cell.transform = tableView.transform
return cell
}
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "BotTableCell", for: indexPath) as! BotTableCell
cell.botMessage.onSizeChange = { [unowned tableView, unowned self] r in
let point = tableView.convert(r.bounds.origin, from: r)
guard let indexPath = tableView.indexPathForRow(at: point) else { return }
if r.shouldTrim {
self.expandedCells.remove(indexPath.row)
print("REMOVE CALLED")
} else {
self.expandedCells.insert(indexPath.row)
print("INSERT CALLED")
}
tableView.reloadData()
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "BotTableCell", for: indexPath) as! BotTableCell
cell.botMessage.shouldTrim = !cell.botMessage.shouldTrim
print("SHOULD TRIM CALLED")
cell.backgroundColor = .clear
}
}
Вот мой TableViewController
Класс:
class TMNEMessageViewController: UITableViewController, UITextViewDelegate {
@IBOutlet weak var navBar: UINavigationItem!
private var observer: AnyObject?
private var needsUpdateViewOnAppearance = true
@IBOutlet var messageBar: MessageBar!
public override var inputAccessoryView: UIView? {return messageBar}
public override var canBecomeFirstResponder: Bool {return true}
private var isVisible: Bool {return isViewLoaded && view.window != nil}
var messages: SortedArray<Activity> { return BotClient.shared.messages }
var expandedCells = Set<Int>()
let readMoreTextAttributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.foregroundColor: UIColor.red,
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16)
]
let readLessTextAttributes = [
NSAttributedString.Key.foregroundColor: UIColor.red,
NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 16)
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 300
tableView.rowHeight = UITableView.automaticDimension
registerCells()
setupObservers()
tableView.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: 0) //flip tableview
BotClient.shared.start { r in
if let _ = r.resource {
print(r.printResponseData())
} else if let error = r.error {
print("ERROR: " + error.localizedDescription)
self.displayError(error.localizedDescription)
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if needsUpdateViewOnAppearance {
tableView.reloadData()
needsUpdateViewOnAppearance = false
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
becomeFirstResponder()
}
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if tableView.contentInset == UIEdgeInsets.zero {
updateContentInset(inset: getContentInset())
}
// tableView.reloadData()
}
func registerCells() {
self.tableView.register(UINib(nibName: "BotTableCell", bundle: nil), forCellReuseIdentifier: "BotTableCell")
self.tableView.register(UINib(nibName: "UserTableViewCell", bundle: nil), forCellReuseIdentifier: "UserTableViewCell")
}
fileprivate func setupObservers() {
// Keyboard Notifications
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardDidHideNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
// BotClient Notifications
NotificationCenter.default.addObserver(self, selector: #selector(handleMessageAdded(notification:)), name: .BotClientDidAddMessageNotification, object: BotClient.shared)
}
@objc
func handleKeyboardNotification(notification: Notification) {
switch notification.name {
case UIResponder.keyboardDidChangeFrameNotification:
if let rect = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
DispatchQueue.main.async {
//print("r \(rect) i \(self.tableView.safeAreaInsets)")
// print(self.tableView.contentInset)
let inset = self.tableView.contentInset
self.updateContentInset(inset: UIEdgeInsets(top: (rect.height + 10) - self.tableView.safeAreaInsets.top, left: inset.left, bottom: inset.bottom, right: inset.right))
}
}
default: return
}
}
func updateContentInset(inset: UIEdgeInsets) {
UIView.animate(withDuration: 0.15, animations: {
self.tableView.contentInset = inset
}, completion: { f in
if self.messages.count > 0 {
self.tableView.scrollToRow(at: IndexPath.init(row: 0, section: 0), at: .top, animated: true)
}
})
}
@objc func handleMessageAdded(notification: Notification) {
DispatchQueue.main.async {
if self.isVisible {
self.tableView.reloadData()
} else {
self.needsUpdateViewOnAppearance = true
}
}
}
func getContentInset() -> UIEdgeInsets {
return UIEdgeInsets(top: max(tableView.safeAreaInsets.top, messageBar.frame.height) - tableView.adjustedContentInset.top, left: 0, bottom: tableView.safeAreaInsets.bottom - tableView.adjustedContentInset.bottom, right: 0)
}
// Err
func displayError(_ message: String?) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}