Home > Software engineering >  Dynamically Create Labels using Swift
Dynamically Create Labels using Swift

Time:01-24

I'm writing a score keeping app for a game and I'd like the players to be able to record multiple stats for games that could have 4, 6, 8 or even more players. I set up my labels as shown below:

    var playerOneReboundMadeLabel = UILabel()
    var playerTwoReboundMadeLabel = UILabel()
    var playerThreeReboundMadeLabel = UILabel()
    var playerFourReboundMadeLabel = UILabel()
    var playerFiveReboundMadeLabel = UILabel()
    var playerSixReboundMadeLabel = UILabel()
    var playerOneScoreLabel = UILabel()
    var playerTwoScoreLabel = UILabel()
    var playerThreeScoreLabel = UILabel()
    var playerFourScoreLabel = UILabel()
    var playerFiveScoreLabel = UILabel()
    var playerSixScoreLabel = UILabel()
    var numberOfPlayers = 6

override func viewDidLoad() {

var playerReboundAttemptLabelArray = [playerOneReboundAttemptsLabel, playerTwoReboundAttemptsLabel, playerThreeReboundAttemptsLabel, playerFourReboundAttemptsLabel, playerFiveReboundAttemptsLabel, playerSixReboundAttemptsLabel]

for player in 1...numberOfPlayers {
            let label = UILabel(frame: CGRect(x: playerOneScoreLabel.frame.maxX, y: playerScoreLabelArray[player-1].frame.minY, width: viewWidth*columnThreeWidth, height: viewHeight*labelHeight))
            label.tag = player 100
            label.backgroundColor = UIColor(red: 255/255, green: 197/255, blue: 142/255, alpha: 1.0)
            label.textAlignment = .center
            label.font = UIFont(name: "AmericanTypewriter-Bold", size: 23)
            label.text = "\(playerReboundAttemptsArray[player-1])"
            label.adjustsFontSizeToFitWidth = true
            label.isUserInteractionEnabled = true
            playerStatsView.addSubview(label)
            playerReboundAttemptLabelArray[player-1] = view.viewWithTag(player 100) as! UILabel
        }
        
        //playerThreeReboundAttemptsLabel = view.viewWithTag(106) as! UILabel
        playerThreeReboundAttemptsLabel.text = "54"
}

When the "playerThreeReboundAttemptsLabel = view.viewWithTag(106) as! UILabel" is commented out the label doesn't change to "54" but when I activate it then it works. I think it may be due to creating a copy of the value in the array, but I don't fully understand it.

I feel like there should be a more Swifty way of doing this, although the above will work by assigning each of the labels outside of the for loop I was hoping someone could help with an more elegant and brief way of creating these that will allow me to do it dynamically by just changing the number of players variable before loading the view.

Thanks!

CodePudding user response:

Eliminate all of the discrete label properties. Just have two label arrays. Then your code becomes something like this:

var playerReboundLabels = [UILabel]()
var playerScoreLabels = [UILabel]()
var numberOfPlayers = 6

override func viewDidLoad() {
    super.viewDidLoad()

    // Create the rebound labels. Do something similar for the score labels
    for player in 0..<numberOfPlayers {
        let label = UILabel()
        label.backgroundColor = UIColor(red: 255/255, green: 197/255, blue: 142/255, alpha: 1.0)
        label.textAlignment = .center
        label.font = UIFont(name: "AmericanTypewriter-Bold", size: 23)
        label.text = "\(playerReboundAttemptsArray[player])"
        label.adjustsFontSizeToFitWidth = true
        label.isUserInteractionEnabled = true
        playerStatsView.addSubview(label)
        playerReboundLabels.append(label)
    }

    // Access a label via index, for example:
    playerReboundLabels[3].text = "54"
}

Look into using UIStackView or constraints to arrange the labels. Much better than trying to assign frames to each label.

  • Related