Home>
Error message

I am trying to make an SNS application using TableView, and I am making a tag button as a function.

AddSubView () four custom views in a custom cell.
① View the user's image and name view
② View the artist's image, name and song name View
③View that displays tags
④View that displays good numbers

There is a problem ③.
In (3), UIButton is addedSubView ().
The layout of the UIButton is decided as follows in the custom view.
When scrolling TableView, the layout may not work or may work.

If i scroll violently, the app will drop.

I would appreciate it if you could tell me how to solve it.

// Here, the size of the tag button is adjusted.
    func adjustSize (tag: UIButton, height: CGFloat) {
// adjustBoldFontSizeForHeight (height :) sets the font size suitable for height to itself.
        tag.adjustBoldFontSizeForHeight (height: height)
// Determines the width of tag: UIButton based on the set font size and text length.
// By doing this, the title of the UIButton is displayed without being omitted.
        let attributes = [NSAttributedString.Key.font: tag.titleLabel? .font]
        let textWidth = tag.titleLabel! .text! .size (withAttributes: attributes) .width
        tag.frame.size = .init (width: textWidth, height: height)
    }
override func layoutSubviews () {
        super.layoutSubviews ()
// 0 ~ 4 tags are created.// The layout I want to realize here is that the tags (UIButton) are set in order from the left edge of the parent view.
// Set the UIButton height to 40% of its own height so that it goes to the second row when it exceeds its own width.
// In addition, from the third that may exceed the width of the self, we use the Bool value to determine.
        let tagButtonHeight = self.frame.height * 0.4
        let tagViewWidth = self.frame.width * 0.9
        let margin = self.frame.width * 0.05
        var previousWidth: CGFloat = 0
        guard let first = firstTag else {
            return
        }
        adjustSize (tag: first, height: tagViewHeight)
        first.leadingAnchor.constraint (equalTo: self.leadingAnchor) .isActive = true
        first.topAnchor.constraint (equalTo: self.topAnchor) .isActive = true
        previousWidth + = first.frame.width + margin

        guard let second = secondTag else {
            return
        }
        adjustSize (tag: second, height: tagViewHeight)
        second.leadingAnchor.constraint (equalTo: first.trailingAnchor, constant: margin) .isActive = true
        second.topAnchor.constraint (equalTo: self.topAnchor) .isActive = true
        previousWidth + = second.frame.width + margin
        guard let third = thirdTag else {
            return
        }
        adjustSize (tag: third, height: tagViewHeight)
        if previousWidth + third.frame.width<tagViewWidth {third.leadingAnchor.constraint (equalTo: second.trailingAnchor, constant: margin) .isActive = true
            third.topAnchor.constraint (equalTo: self.topAnchor) .isActive = true
            previousWidth + = third.frame.width + margin
            thirdIsOver = false
        } else {
            third.leadingAnchor.constraint (equalTo: self.leadingAnchor) .isActive = true
            third.topAnchor.constraint (equalTo: self.centerYAnchor) .isActive = true
            previousWidth + = third.frame.width + margin
            thirdIsOver = true
        }
        guard let fourth = fourthTag else {
            return
        }
        adjustSize (tag: fourth, height: tagViewHeight)
        if thirdIsOver! {
            fourth.leadingAnchor.constraint (equalTo: third.trailingAnchor, constant: margin) .isActive = true
            fourth.topAnchor.constraint (equalTo: self.centerYAnchor) .isActive = true
        } else if previousWidth + fourth.frame.width<tagViewWidth {
            fourth.leadingAnchor.constraint (equalTo: third.trailingAnchor, constant: margin) .isActive = true
        } else {
            fourth.leadingAnchor.constraint (equalTo: self.leadingAnchor) .isActive = true
            fourth.topAnchor.constraint (equalTo: self.centerYAnchor) .isActive = true
        }
    }

  • Answer # 1

    I don't understand the code because I don't understand the code well.
    Did you create a CustomCell class?
    (class *** Cell: UITableViewCell {} and missing code)
    Do you use Storyboard? ? ?
    (40% etc. but I don't know what is actually happening)

    Probably, override func layoutSubviews () {}
    Is read only once when the ViewController is created, so
    func tableView cellForRowAt using indexPath:
    I have to rewrite my code to adjust the position
    Different cell settings are applied to reused cells as they are,
    I think the cause is that the display is correct or not.
    And it will fall when it becomes an unreasonable setting.

    Examples and notes below

    // Data
    struct CDData {
        let rank: Int
        let title: String
        let artist: String
    }
    // Custom cell
    import UIKit
    class CustomCell: UITableViewCell {
        @IBOutlet weak var titleLabel: UILabel
        @IBOutlet weak var artistLabel: UILabel
        override func layoutSubviews () {
            super.layoutSubviews ()
            print ("CustomCell, layoutSubviews")
            self.label.textColor = UIColor.red //<-I think this is understandable if you see it in print, but it is only called once (it is not called at reuse)
        }
        func bind1 (data: CDData) {
            self.titleLabel.text = data.title
            self.artistLabel.text = data.artist
            if data.rank == 1 {
               self.titleLabel.textColor = UIColor.red
            } else {
               self.titleLabel.textColor = UIColor.black //<-If you forget this, the color will turn red in unexpected places (where it is reused).
            }
        }
        // By the way, if you are yourself, make sure you know where to look when you change and divide as follows.
        func bind2 (data: CDData) {
            makeUserItems ()
            makeArtistItems (cdData: data)
            makeTag ()
            makeGood ()
        }
        private func makeUserItem () {
        }
        ...Continue
    }
    // TableView
    import UIKit
    class TableViewController: UIViewController {
        @IBOutlet weak var tableView: UITableView!
        var cDDataList: [CDData] = []
        override func viewDidLoad () {
            self.cDDataList = [
                CDData (rank: 1, title: "Turning up", artist: "Arashi"),
                CDData (rank: 2, title: "Horse and Deer", artist: "Genshi Yonezu"),
                CDData (rank: 3, title: "Pretender", artist: "official 髭 男 dism")
            ]
        }
        // Because it is awkward, it is omitted
        func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath)->UITableViewCell {
            let cell = tableView.dequeueReusableCell (withIdentifier: "CustomCell") as! CustomCell
            cell.bind (data: self.cDDataList [indexPath.row])
            return cell
        }
    }

Related articles

Trends