文本重叠应该删除的文本
Text Overlapping Text That Should've deleted
HI, so this is my vc for a view where I save info about a plane (the type and rego). It saves the plane and deletes and you can close the app and come back and it saves it there in the core data model but I have a weird problem. After you make a plane and it shows in the table view and add a few more planes (table view cell which has info) then the labels which display the info start to overlap with what should be deleted information. The pictures bellow show what I mean. Any help would be greatly appreciated.
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var typeField: UITextField?
var regoField: UITextField?
@IBAction func addPlaneButton(_ sender: Any) {
let alertController = UIAlertController(title: "New Plane", message: "Please Input The Type And Registration", preferredStyle: .alert)
alertController.addTextField(configurationHandler: typeField)
alertController.addTextField(configurationHandler: regoField)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
let saveAction = UIAlertAction(title: "Save", style: .default, handler: self.savePlane)
alertController.addAction(cancelAction)
alertController.addAction(saveAction)
self.present(alertController, animated: true)
print("Add Plane Pressed")
}
func typeField(textField: UITextField!) {
typeField = textField
typeField?.placeholder = "Aircraft Type"
}
func regoField(textField: UITextField!) {
regoField = textField
regoField?.placeholder = "Aircraft Registration"
}
@IBOutlet weak var tableView: UITableView!
var timer = Timer()
let utcItem = UIBarButtonItem()
let utcLbl = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
//Table View
tableView.delegate = self
tableView.dataSource = self
self.tableView.rowHeight = 88
setupView()
}
//////Functions////
func setupView() {
//UTC Time Formatter
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.dateFormat = "HH:mm"
_ = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
//UTC Time
utcLbl.frame = CGRect(x: 0, y: 0, width: 100, height: 20)
utcLbl.text = "\(dateFormatter.string(from: Date())) UTC"
utcItem.customView = utcLbl
utcLbl.backgroundColor = UIColor.init(fromHexCode: "4FB7F1")
utcLbl.layer.cornerRadius = 10
utcLbl.textAlignment = .center
utcLbl.layer.masksToBounds = true // Or utcLbl.clipsToBounds = true
self.navigationItem.setLeftBarButtonItems([utcItem], animated: true)
// Large Title
self.title = "Planes"
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.font: UIFont(name: "Avenir-Black", size: 35)!]
self.navigationController?.navigationBar.prefersLargeTitles = true
let customBlue = UIColor(red:0.08, green:0.38, blue:0.75, alpha:1.0)
navigationController?.navigationBar.barTintColor = customBlue
}
//Constant UTC Time Lbl
@objc func updateTime() {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "UTC")
formatter.dateFormat = "HH:mm"
utcLbl.text = formatter.string(from: Date()) + " UTC"
}
//Save the Plane Info
func savePlane(alert: UIAlertAction) {
if typeField?.text != "" || regoField?.text != "" {
let newLog = NSEntityDescription.insertNewObject(forEntityName: "Planes", into: context)
newLog.setValue(self.typeField?.text, forKey: "type")
newLog.setValue(self.regoField?.text, forKey: "rego")
do{
try context.save()
}
catch {
print(error)
}
//Making the table update itself when user logs the plane
self.fetchData()
self.tableView.reloadData()
}
print("Plane Saved")
}
func fetchData() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do{
planeArray = try context.fetch(Planes.fetchRequest())
}
catch{
print(error)
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
if editingStyle == .delete {
let save = planeArray[indexPath.row]
context.delete(save)
(UIApplication.shared.delegate as! AppDelegate).saveContext()
do {
planeArray = try context.fetch(Planes.fetchRequest())
}
catch {
print(error)
}
tableView.reloadData()
}
}
//Table View Functions
public func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (planeArray.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//Plane Pic
let planeView = UIImageView()
planeView.frame = CGRect(x: 0, y: 0, width: 69, height: 67)
//planeView.center = CGPoint(x: cell.center.x - 150, y: cell.center.y)
planeView.center = CGPoint(x: cell.center.x - 145, y: cell.center.y)
let planeImage: UIImage = UIImage(named: "plane")!
planeView.image = planeImage
cell.addSubview(planeView)
//Type Label
let type = UILabel()
type.frame = CGRect(x: 0, y: 0, width: 45, height: 21)
type.center = CGPoint(x: cell.center.x - 80, y: cell.center.y - 22.5)
type.text = "Type:"
type.font = UIFont(name: "Montserrat-Medium", size: 17)
cell.addSubview(type)
//Type Answer
let typeAnswer = UILabel()
typeAnswer.frame = CGRect(x: 0, y: 0, width: 220, height: 21)
typeAnswer.center = CGPoint(x: cell.center.x + 62.5, y: cell.center.y - 22.5)
typeAnswer.text = ""
typeAnswer.font = UIFont(name: "Montserrat-Light", size: 17)
typeAnswer.textAlignment = .right
cell.addSubview(typeAnswer)
//Rego Label
let rego = UILabel()
rego.frame = CGRect(x: 0, y: 0, width: 110, height: 21)
rego.center = CGPoint(x: cell.center.x - 47.5, y: cell.center.y + 18.5)
rego.text = "Registration:"
rego.font = UIFont(name: "Montserrat-Medium", size: 17)
cell.addSubview(rego)
//rego answer
let regoAnswer = UILabel()
regoAnswer.frame = CGRect(x: 0, y: 0, width: 160, height: 21)
regoAnswer.center = CGPoint(x: cell.center.x + 92.5, y: cell.center.y + 18.5)
regoAnswer.text = ""
regoAnswer.font = UIFont(name: "Montserrat-Light", size: 17)
regoAnswer.textAlignment = .right
cell.addSubview(regoAnswer)
let save = planeArray[indexPath.row]
typeAnswer.text = save.type
regoAnswer.text = save.rego
return cell
}
override func viewWillAppear(_ animated: Bool) {
//Making the table update itself when user logs the plane
fetchData()
tableView.reloadData()
}
}
UITableView
重复使用单元格。在你的例子中,当第一次创建单元格时,你向它添加一个 UILabel
。下次加载此单元格时,UITableView
会重新使用现有单元格,并且 cellForRowAt
会向此单元格添加另一个 UILabel
。正确的实现是创建自定义 UITableViewCell
并重置 cellForRowAt
方法中所有属性的值。
您可以尝试下面的操作(请注意,这只是一个粗略的实现,假设您了解 ios 编程的基础知识。如果不是这样,我建议您研究一下有点):
添加自定义表格视图单元格
class CustomTableViewCell: UITableViewCell {
@IBOutlet weak var imgViewPlane: UIImageView!
@IBOutlet weak var lblType: UILabel!
@IBOutlet weak var lblTypeAnswer: UILabel!
@IBOutlet weak var lblRego: UILabel!
@IBOutlet weak var lblRegoAnswer: UILabel!
}
在情节提要表视图和 link IBOutlet
中创建一个动态原型单元格。然后在你的cellForRowAt
中,做这样的事情
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomTableViewCell
cell.imgViewPlane.image = planeImage
cell.lblType.text = "Type:"
cell.lblTypeAnswer.text = planeArray[indexPath.row].type
cell.lblRego.text = "Registration:"
cell.lblRegoAnswer.text = planeArray[indexPath.row].rego
return cell
}
每次单元格出列时,您都在向单元格添加新的子视图。
我建议您将这些视图、标签等创建为 UITableViewCell
子类中的 lazy
变量,并将它们添加为 awakeFromNib()
中的子视图
class YourCell: UITableViewCell {
lazy var label: UILabel = {
var label = UILabel(...)
...
return label
}()
...
override func awakeFromNib() {
addSubview(label)
...
}
}
..... 或者如果你使用的是故事板
,则使用IBOutlet
然后在 cellForRowAt
中只需更改向下转换单元子类的视图的属性
let cell = ... as! YourCell
cell.label.text = ""
cell.anotherLabel.isHidden = true
...
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var typeField: UITextField?
var regoField: UITextField?
@IBAction func addPlaneButton(_ sender: Any) {
let alertController = UIAlertController(title: "New Plane", message: "Please Input The Type And Registration", preferredStyle: .alert)
alertController.addTextField(configurationHandler: typeField)
alertController.addTextField(configurationHandler: regoField)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
let saveAction = UIAlertAction(title: "Save", style: .default, handler: self.savePlane)
alertController.addAction(cancelAction)
alertController.addAction(saveAction)
self.present(alertController, animated: true)
print("Add Plane Pressed")
}
func typeField(textField: UITextField!) {
typeField = textField
typeField?.placeholder = "Aircraft Type"
}
func regoField(textField: UITextField!) {
regoField = textField
regoField?.placeholder = "Aircraft Registration"
}
@IBOutlet weak var tableView: UITableView!
var timer = Timer()
let utcItem = UIBarButtonItem()
let utcLbl = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
//Table View
tableView.delegate = self
tableView.dataSource = self
self.tableView.rowHeight = 88
setupView()
}
//////Functions////
func setupView() {
//UTC Time Formatter
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.dateFormat = "HH:mm"
_ = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
//UTC Time
utcLbl.frame = CGRect(x: 0, y: 0, width: 100, height: 20)
utcLbl.text = "\(dateFormatter.string(from: Date())) UTC"
utcItem.customView = utcLbl
utcLbl.backgroundColor = UIColor.init(fromHexCode: "4FB7F1")
utcLbl.layer.cornerRadius = 10
utcLbl.textAlignment = .center
utcLbl.layer.masksToBounds = true // Or utcLbl.clipsToBounds = true
self.navigationItem.setLeftBarButtonItems([utcItem], animated: true)
// Large Title
self.title = "Planes"
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.font: UIFont(name: "Avenir-Black", size: 35)!]
self.navigationController?.navigationBar.prefersLargeTitles = true
let customBlue = UIColor(red:0.08, green:0.38, blue:0.75, alpha:1.0)
navigationController?.navigationBar.barTintColor = customBlue
}
//Constant UTC Time Lbl
@objc func updateTime() {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "UTC")
formatter.dateFormat = "HH:mm"
utcLbl.text = formatter.string(from: Date()) + " UTC"
}
//Save the Plane Info
func savePlane(alert: UIAlertAction) {
if typeField?.text != "" || regoField?.text != "" {
let newLog = NSEntityDescription.insertNewObject(forEntityName: "Planes", into: context)
newLog.setValue(self.typeField?.text, forKey: "type")
newLog.setValue(self.regoField?.text, forKey: "rego")
do{
try context.save()
}
catch {
print(error)
}
//Making the table update itself when user logs the plane
self.fetchData()
self.tableView.reloadData()
}
print("Plane Saved")
}
func fetchData() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do{
planeArray = try context.fetch(Planes.fetchRequest())
}
catch{
print(error)
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
if editingStyle == .delete {
let save = planeArray[indexPath.row]
context.delete(save)
(UIApplication.shared.delegate as! AppDelegate).saveContext()
do {
planeArray = try context.fetch(Planes.fetchRequest())
}
catch {
print(error)
}
tableView.reloadData()
}
}
//Table View Functions
public func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (planeArray.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//Plane Pic
let planeView = UIImageView()
planeView.frame = CGRect(x: 0, y: 0, width: 69, height: 67)
//planeView.center = CGPoint(x: cell.center.x - 150, y: cell.center.y)
planeView.center = CGPoint(x: cell.center.x - 145, y: cell.center.y)
let planeImage: UIImage = UIImage(named: "plane")!
planeView.image = planeImage
cell.addSubview(planeView)
//Type Label
let type = UILabel()
type.frame = CGRect(x: 0, y: 0, width: 45, height: 21)
type.center = CGPoint(x: cell.center.x - 80, y: cell.center.y - 22.5)
type.text = "Type:"
type.font = UIFont(name: "Montserrat-Medium", size: 17)
cell.addSubview(type)
//Type Answer
let typeAnswer = UILabel()
typeAnswer.frame = CGRect(x: 0, y: 0, width: 220, height: 21)
typeAnswer.center = CGPoint(x: cell.center.x + 62.5, y: cell.center.y - 22.5)
typeAnswer.text = ""
typeAnswer.font = UIFont(name: "Montserrat-Light", size: 17)
typeAnswer.textAlignment = .right
cell.addSubview(typeAnswer)
//Rego Label
let rego = UILabel()
rego.frame = CGRect(x: 0, y: 0, width: 110, height: 21)
rego.center = CGPoint(x: cell.center.x - 47.5, y: cell.center.y + 18.5)
rego.text = "Registration:"
rego.font = UIFont(name: "Montserrat-Medium", size: 17)
cell.addSubview(rego)
//rego answer
let regoAnswer = UILabel()
regoAnswer.frame = CGRect(x: 0, y: 0, width: 160, height: 21)
regoAnswer.center = CGPoint(x: cell.center.x + 92.5, y: cell.center.y + 18.5)
regoAnswer.text = ""
regoAnswer.font = UIFont(name: "Montserrat-Light", size: 17)
regoAnswer.textAlignment = .right
cell.addSubview(regoAnswer)
let save = planeArray[indexPath.row]
typeAnswer.text = save.type
regoAnswer.text = save.rego
return cell
}
override func viewWillAppear(_ animated: Bool) {
//Making the table update itself when user logs the plane
fetchData()
tableView.reloadData()
}
}
UITableView
重复使用单元格。在你的例子中,当第一次创建单元格时,你向它添加一个 UILabel
。下次加载此单元格时,UITableView
会重新使用现有单元格,并且 cellForRowAt
会向此单元格添加另一个 UILabel
。正确的实现是创建自定义 UITableViewCell
并重置 cellForRowAt
方法中所有属性的值。
您可以尝试下面的操作(请注意,这只是一个粗略的实现,假设您了解 ios 编程的基础知识。如果不是这样,我建议您研究一下有点):
添加自定义表格视图单元格
class CustomTableViewCell: UITableViewCell {
@IBOutlet weak var imgViewPlane: UIImageView!
@IBOutlet weak var lblType: UILabel!
@IBOutlet weak var lblTypeAnswer: UILabel!
@IBOutlet weak var lblRego: UILabel!
@IBOutlet weak var lblRegoAnswer: UILabel!
}
在情节提要表视图和 link IBOutlet
中创建一个动态原型单元格。然后在你的cellForRowAt
中,做这样的事情
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomTableViewCell
cell.imgViewPlane.image = planeImage
cell.lblType.text = "Type:"
cell.lblTypeAnswer.text = planeArray[indexPath.row].type
cell.lblRego.text = "Registration:"
cell.lblRegoAnswer.text = planeArray[indexPath.row].rego
return cell
}
每次单元格出列时,您都在向单元格添加新的子视图。
我建议您将这些视图、标签等创建为 UITableViewCell
子类中的 lazy
变量,并将它们添加为 awakeFromNib()
class YourCell: UITableViewCell {
lazy var label: UILabel = {
var label = UILabel(...)
...
return label
}()
...
override func awakeFromNib() {
addSubview(label)
...
}
}
..... 或者如果你使用的是故事板
,则使用IBOutlet
然后在 cellForRowAt
中只需更改向下转换单元子类的视图的属性
let cell = ... as! YourCell
cell.label.text = ""
cell.anotherLabel.isHidden = true
...