UILabel progressbar

A UILabel that acts as a progress bar, check the Pixplicity Authenticator app to see an example (Android here, iOS currently not yet). Simply add a UILabel to your view through the Xcode interface builder and subclass it to LoaderUILabel. Or programmatically add it to your view.

Connect it to your viewcontroller and simply start setting its progress to get it to start loading:

mLoaderLabel.applyLoaderProgress(to: 60.0)

The following piece of code: UIColor.primaryColor is from another cookbook snippet

import Foundation
import UIKit

class LoaderUILabel: UILabel {
    
    var maskLabel: UILabel?
    var mPercentage: CGFloat = 0.0
    final var COLOR_CHANGE_THRESHOLD: CGFloat = 0.25
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    private func applyAttributes() {
        maskLabel?.attributedText = self.attributedText
        maskLabel?.lineBreakMode = .byClipping
        maskLabel?.textColor = mPercentage > COLOR_CHANGE_THRESHOLD ? UIColor.tokenTextColor : UIColor.tokenUrgentColor
    }
    
    func applyLoaderProgress(to percentage: CGFloat) {
        
        mPercentage = percentage
        if(maskLabel == nil) {
            
            maskLabel = UILabel(frame: self.frame)
            applyAttributes()
            self.addSubview(maskLabel!)
        }
        
        maskLabel?.frame.size.width = self.intrinsicContentSize.width * percentage
        maskLabel?.textColor = percentage > COLOR_CHANGE_THRESHOLD ? UIColor.tokenTextColor : UIColor.tokenUrgentColor
        maskLabel?.text = self.text
    }
    
    //Used to remove and re-add the view and as such get its constraints corrected if the main view shifted positions
    func shiftMask(){
        maskLabel?.removeFromSuperview()
        maskLabel = nil
    }
    
    override func drawText(in rect: CGRect) {
        super.drawText(in: rect)
        applyAttributes()
    }
    
}

This is best used in a situation where no constraints need to be applied to the main label. In a situation where the label has constraints applied to it, these need to be applied to the masklabel as well. These can be retrieved and applied in the following manner:

func applyConstraints() {
    self.constraints.forEach { constraint in
        let maskConstraint = NSLayoutConstraint(item: maskLabel!, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: constraint.secondItem, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant)
        maskLabel?.addConstraint(maskConstraint)
    }
}

Apply this after the initialization and adding of the mask subview.