I'm making a chat app and trying to figure out table cells reuse mechanics. I'm having trouble with aligning chat bubbles to left and right, depending on incoming/ougoing message. What i have right now is:
class ConversationTableViewCell: UITableViewCell {
#IBOutlet weak var messageTextLabel: UILabel?
#IBOutlet weak var messageView: UIView?
#IBOutlet weak var trailingPaddingConstraint: NSLayoutConstraint?
#IBOutlet weak var leadingPaddingConstraint: NSLayoutConstraint?
func configure(with data: ConversationViewController.ConversationDataModel.Message) {
messageView?.layer.cornerRadius = 12
messageTextLabel?.text = data.text
switch data.messageType {
case .incoming:
trailingPaddingConstraint?.isActive = false
leadingPaddingConstraint?.isActive = true
messageView?.backgroundColor = UIColor(named: "IncomingMessage") ?? .gray
case .outgoing:
trailingPaddingConstraint?.isActive = true
leadingPaddingConstraint?.isActive = false
messageView?.backgroundColor = UIColor(named: "OutgoingMessage") ?? .green
}
}
}
as you can see i'm enabling or disabling the needed constraint depending on message type, but it seems like these constraints (and only them) reset when a cell is being reused, causing the bubble to align to leading side. What can i do to successfully update constraints and not run into such problem?
I figured out that setting .isActive to false actually removes the constraint (sets the property to nil). As stated in this answer i tried to make constraint class properties not weak and everything worked!
now code looks like this:
class ConversationTableViewCell: UITableViewCell {
#IBOutlet weak var messageTextLabel: UILabel?
#IBOutlet weak var messageView: UIView?
#IBOutlet var trailingPaddingConstraint: NSLayoutConstraint? //not weak
#IBOutlet var leadingPaddingConstraint: NSLayoutConstraint? //not weak
func configure(with data: ConversationViewController.ConversationDataModel.Message) {
messageView?.layer.cornerRadius = 12
messageTextLabel?.text = data.text
switch data.messageType {
case .incoming:
trailingPaddingConstraint?.isActive = false
leadingPaddingConstraint?.isActive = true
messageView?.backgroundColor = UIColor(named: "IncomingMessage") ?? .gray
case .outgoing:
trailingPaddingConstraint?.isActive = true
leadingPaddingConstraint?.isActive = false
messageView?.backgroundColor = UIColor(named: "OutgoingMessage") ?? .green
}
}
}
Related
According my question, I have to pass a data to my collection view cell
It made laggy when scroll. It happened because my setup data function, it pass too big of data but I have no idea how to fix it.
My cell class .
class VerificationStepCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var stepLabel: UILabel!
#IBOutlet weak var stepTitleLabel: UILabel!
#IBOutlet weak var stepNoLabel: UILabel!
#IBOutlet weak var iconImageView: UIImageView!
#IBOutlet weak var stepDescriptionLabel: UILabel!
#IBOutlet weak var stepStatusLabel: UILabel!
#IBOutlet weak var stepStatusView: UIView!
#IBOutlet weak var buttonStatus: BaseButton!
var currentStepType: VerifyAccountStepType?
var currentStatus: UserLevelInfoStatus?
var data: HomeModels.ViewModel.VerifyAccountStepModel? = nil
override func awakeFromNib() {
super.awakeFromNib()
self.setupView()
}
private func setupView() {
self.stepStatusView.layer.cornerRadius = self.stepStatusView.frame.height / 2
}
func setupData() {
guard let data = self.data else { return }
self.currentStepType = data.stepType
self.currentStatus = data.stepStatus
self.stepStatusView.isHidden = data.stepStatus == .notVerify
self.stepLabel.text = "Step\(data.stepNo)"
self.stepTitleLabel.text = data.stepTitle
self.stepNoLabel.text = "\(data.stepNo)"
self.iconImageView.image = data.stepIconImage
self.stepDescriptionLabel.text = data.stepDescription
self.stepStatusLabel.text = "home_unverified_account_\(data.stepStatus.rawValue)_status".localized()
switch data.stepStatus {
case .approve:
self.buttonStatus.setIsEnable(false)
self.buttonStatus.setTitle(data.stepButtonTitle, for: .normal)
self.stepStatusView.backgroundColor = UIColor.Yellows.brighterYellow
self.stepStatusLabel.textColor = .black
case .notVerify:
self.buttonStatus.setIsEnable(true)
self.buttonStatus.setTitle(data.stepButtonTitle, for: .normal)
self.stepStatusLabel.textColor = .white
case .reject:
self.buttonStatus.setIsEnable(true)
self.buttonStatus.setTitle("แก้ไข", for: .normal)
self.stepStatusView.backgroundColor = UIColor.Reds.loss
self.stepStatusLabel.textColor = .white
case .pending:
self.buttonStatus.setIsEnable(false)
self.buttonStatus.setTitle(data.stepButtonTitle, for: .normal)
self.stepStatusView.backgroundColor = UIColor.Oranges.deepOrange
self.stepStatusLabel.textColor = .white
}
}
}
I know my data is too big but It have to, Has anyone ever face with this problem?
Thank you
Update solution
It found my problem already, It cause from my localized text function.
After I removed it everything working fine!~
I have two text fields, one button, and four labels.
When you push the button, it should update the four labels.
Label 1: name
Label 2: email
Label 3: name (same data as label 1)
Label 4: email (same data as label 2)
I was experimenting under viewDidLoad() to see if I can make another var and update my last label. No error when I run the code, but it turns out "empty" in the simulator.
Can anyone explain why?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var emailInput: UITextField!
#IBOutlet weak var nameInput: UITextField!
#IBOutlet weak var label: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBAction func actionButton(_ sender: Any) {
var text = nameInput.text
var email = emailInput.text
label.text = text
label2.text = email
label3.text = text
}
//where i experimented:
override func viewDidLoad() {
super.viewDidLoad()
var email2 = emailInput.text
label4.text = email2
}
}
Change
label4.text = email2
To
label4.text = "howdy"
Now you will see something in your interface.
The viewDidLoad method called in the beginning perfectly. But the label not showing any data because initially the textfield has no value. That's the label not contains any data.
Please set any value to the label initially. Like
label4.text = "Something"
Hope you can understand that the viewDidLoad is called perfectly.
My uitableview consists of 10 cells and each cell has 2 uitextfield's.
I need to take values from each uitextfield in each cell and add it to an array
// my custom cell
class MatchTableViewCell: UITableViewCell, UITextFieldDelegate {
#IBOutlet weak var Team2Score: UITextField!
#IBOutlet weak var Team1Score: UITextField!
#IBOutlet weak var Team2: UILabel!
#IBOutlet weak var Image2: UIImageView!
#IBOutlet weak var Image1: UIImageView!
#IBOutlet weak var Team1: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Make sure in the cell initializer for tableviewcontroller that your using your custom cell name and that you've set your identifier correctly. Then just initalize a cell and say something to the effect of
cell.Team2Score.text = "100"
you will need a global array to hold the strings. So..
var wordArray: [String] = []
you will need to add a button within the cell so when you hit the button it will add (append in the input of string (letters) to the array.
You need to add a tag to the button to know which cell it was clicked in.
button.tag = indexPath.row
#IBaction button(sender: UIButton){
var team2Words = Team2Score.text
wordArray.append(team2Words)
// do the samething for Team1Score
// you can use and if statement to check if one or the other one is empty
}
This will give you a lead
Can anybody tell me why my photos go beyond the boundary of UIImageView?
The pictures end up covering the buttons below it.
My code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var Photo: UIImageView!
#IBOutlet var QuestionLabel: UILabel!
#IBOutlet var Button1: UIButton!
#IBOutlet var Button2: UIButton!
#IBOutlet var Button3: UIButton!
#IBOutlet var Button4: UIButton!
#IBOutlet var LabelEnd: UILabel!
var CorrectAnswer = String()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
Hide()
Photo.layer.cornerRadius = self.Photo.frame.size.width / 10
Photo.clipsToBounds = true
Photo.layer.masksToBounds = true
Photo.layer.borderWidth = 1
Photo.layer.borderColor = UIColor.blackColor().CGColor
Photo.contentMode = .ScaleAspectFit
Photo.contentMode = .ScaleAspectFill
RandomQuestions()
}
I apologize for being such a novice, just learning how to code.
Are you sure it's going beyond the boundary of your image view?
Try printing out the frame of your view to double check. Doesn't look like you have constraints set up from that screenshot - maybe your image view is sized to fit.
I'm trying to change the labels of a viewController after a certain action is taken from a modal view which triggers an unwind segue.
Once unwind segue happens the labels of the current view (the one which the modal was covering) should be changed.
My current attempt at doing this is resulting in a "unexpectedly found nil while unwrapping an Optional value" error. Here is the code:
class DataViewController: UIViewController {
var experiment: NSDictionary?
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var bodyLabel: UILabel!
#IBOutlet weak var tlRightLine: UIImageView!
#IBOutlet weak var tlLeftLine: UIImageView!
#IBOutlet weak var brRightLine: UIImageView!
#IBOutlet weak var brLeftLine: UIImageView!
#IBOutlet weak var bodyTest: UITextView!
#IBAction func removeExperimentSegue(unwindSegue:UIStoryboardSegue) {
removeExperiment = true
titleLabel.text = "Done"
bodyLabel.text = "Done"
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if let dict: NSDictionary = experiment {
if let title = dict.objectForKey("title") as? String {
self.titleLabel!.text = title
}
if let body = dict.objectForKey("body") as? String {
self.bodyTest!.text = body
}
} else {
self.titleLabel!.text = ""
self.bodyLabel!.text = ""
}
}
}
What am I doing wrong?
I did! I ended up using a global boolean variable. I set it true on the initial load of the menu and then had it flip to false during the unwind segue.
var removeExperiment = false
class DataViewController: UIViewController {
#IBAction func removeExperimentSegue(unwindSegue:UIStoryboardSegue) {
removeExperiment = true
}
if removeExperiment == true {
doneLabel.text = "You've completed this experiment. You won't see it again unless you hit 'Reset' from the Home menu."
}
}
Hope that helps!