Swift UIButton Subclass and change color based on variable





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







4















I'm using a subclass for my UIButton and it has a variable called isActive. I need to change the button border color based on that variable. This variable will change programmatically. Please help me with this.



@IBDesignable
class buttonCTAOutlineDark: UIButton {

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}

override func prepareForInterfaceBuilder() {
commonInit()
}

@IBInspectable var isActive: Bool {
get {
return self.isActive
}
set (active) {
if active {
commonInit(isActive: active)
}
}
}

func commonInit(isActive: Bool = false) {
self.backgroundColor = .clear
self.layer.cornerRadius = 4
self.layer.borderWidth = 1

if (isActive) {
self.tintColor = ACTIVE_COLOR
self.layer.borderColor = ACTIVE_COLOR.cgColor
} else {
self.tintColor = nil
self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
}
}
}









share|improve this question


















  • 1





    Use property observer didSet, willSet. whenever you will update properties value those method will call. have a look on it nshipster.com/swift-property-observers

    – Kazi Abdullah Al Mamun
    Nov 29 '18 at 6:25











  • @hashHb get {return self.isActive} will be called recursively. So instead of that try {return isActive}. Also in set (active), commonInit method will be called only when active is true. so you could try set (active) { isActive = active;commonInit(isActive: active)}

    – Natarajan
    Nov 29 '18 at 6:44













  • Personally I wouldn't recommend using those property observers at all, since it isn'r clear for the caller what sideeffects property changes can have. I would just create a method for it, that way, it is more clear for the caller that things can change.

    – J. Doe
    Nov 29 '18 at 8:13


















4















I'm using a subclass for my UIButton and it has a variable called isActive. I need to change the button border color based on that variable. This variable will change programmatically. Please help me with this.



@IBDesignable
class buttonCTAOutlineDark: UIButton {

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}

override func prepareForInterfaceBuilder() {
commonInit()
}

@IBInspectable var isActive: Bool {
get {
return self.isActive
}
set (active) {
if active {
commonInit(isActive: active)
}
}
}

func commonInit(isActive: Bool = false) {
self.backgroundColor = .clear
self.layer.cornerRadius = 4
self.layer.borderWidth = 1

if (isActive) {
self.tintColor = ACTIVE_COLOR
self.layer.borderColor = ACTIVE_COLOR.cgColor
} else {
self.tintColor = nil
self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
}
}
}









share|improve this question


















  • 1





    Use property observer didSet, willSet. whenever you will update properties value those method will call. have a look on it nshipster.com/swift-property-observers

    – Kazi Abdullah Al Mamun
    Nov 29 '18 at 6:25











  • @hashHb get {return self.isActive} will be called recursively. So instead of that try {return isActive}. Also in set (active), commonInit method will be called only when active is true. so you could try set (active) { isActive = active;commonInit(isActive: active)}

    – Natarajan
    Nov 29 '18 at 6:44













  • Personally I wouldn't recommend using those property observers at all, since it isn'r clear for the caller what sideeffects property changes can have. I would just create a method for it, that way, it is more clear for the caller that things can change.

    – J. Doe
    Nov 29 '18 at 8:13














4












4








4








I'm using a subclass for my UIButton and it has a variable called isActive. I need to change the button border color based on that variable. This variable will change programmatically. Please help me with this.



@IBDesignable
class buttonCTAOutlineDark: UIButton {

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}

override func prepareForInterfaceBuilder() {
commonInit()
}

@IBInspectable var isActive: Bool {
get {
return self.isActive
}
set (active) {
if active {
commonInit(isActive: active)
}
}
}

func commonInit(isActive: Bool = false) {
self.backgroundColor = .clear
self.layer.cornerRadius = 4
self.layer.borderWidth = 1

if (isActive) {
self.tintColor = ACTIVE_COLOR
self.layer.borderColor = ACTIVE_COLOR.cgColor
} else {
self.tintColor = nil
self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
}
}
}









share|improve this question














I'm using a subclass for my UIButton and it has a variable called isActive. I need to change the button border color based on that variable. This variable will change programmatically. Please help me with this.



@IBDesignable
class buttonCTAOutlineDark: UIButton {

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}

override func prepareForInterfaceBuilder() {
commonInit()
}

@IBInspectable var isActive: Bool {
get {
return self.isActive
}
set (active) {
if active {
commonInit(isActive: active)
}
}
}

func commonInit(isActive: Bool = false) {
self.backgroundColor = .clear
self.layer.cornerRadius = 4
self.layer.borderWidth = 1

if (isActive) {
self.tintColor = ACTIVE_COLOR
self.layer.borderColor = ACTIVE_COLOR.cgColor
} else {
self.tintColor = nil
self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
}
}
}






ios swift uibutton subclass programmatically






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 29 '18 at 6:22









hashHbhashHb

436




436








  • 1





    Use property observer didSet, willSet. whenever you will update properties value those method will call. have a look on it nshipster.com/swift-property-observers

    – Kazi Abdullah Al Mamun
    Nov 29 '18 at 6:25











  • @hashHb get {return self.isActive} will be called recursively. So instead of that try {return isActive}. Also in set (active), commonInit method will be called only when active is true. so you could try set (active) { isActive = active;commonInit(isActive: active)}

    – Natarajan
    Nov 29 '18 at 6:44













  • Personally I wouldn't recommend using those property observers at all, since it isn'r clear for the caller what sideeffects property changes can have. I would just create a method for it, that way, it is more clear for the caller that things can change.

    – J. Doe
    Nov 29 '18 at 8:13














  • 1





    Use property observer didSet, willSet. whenever you will update properties value those method will call. have a look on it nshipster.com/swift-property-observers

    – Kazi Abdullah Al Mamun
    Nov 29 '18 at 6:25











  • @hashHb get {return self.isActive} will be called recursively. So instead of that try {return isActive}. Also in set (active), commonInit method will be called only when active is true. so you could try set (active) { isActive = active;commonInit(isActive: active)}

    – Natarajan
    Nov 29 '18 at 6:44













  • Personally I wouldn't recommend using those property observers at all, since it isn'r clear for the caller what sideeffects property changes can have. I would just create a method for it, that way, it is more clear for the caller that things can change.

    – J. Doe
    Nov 29 '18 at 8:13








1




1





Use property observer didSet, willSet. whenever you will update properties value those method will call. have a look on it nshipster.com/swift-property-observers

– Kazi Abdullah Al Mamun
Nov 29 '18 at 6:25





Use property observer didSet, willSet. whenever you will update properties value those method will call. have a look on it nshipster.com/swift-property-observers

– Kazi Abdullah Al Mamun
Nov 29 '18 at 6:25













@hashHb get {return self.isActive} will be called recursively. So instead of that try {return isActive}. Also in set (active), commonInit method will be called only when active is true. so you could try set (active) { isActive = active;commonInit(isActive: active)}

– Natarajan
Nov 29 '18 at 6:44







@hashHb get {return self.isActive} will be called recursively. So instead of that try {return isActive}. Also in set (active), commonInit method will be called only when active is true. so you could try set (active) { isActive = active;commonInit(isActive: active)}

– Natarajan
Nov 29 '18 at 6:44















Personally I wouldn't recommend using those property observers at all, since it isn'r clear for the caller what sideeffects property changes can have. I would just create a method for it, that way, it is more clear for the caller that things can change.

– J. Doe
Nov 29 '18 at 8:13





Personally I wouldn't recommend using those property observers at all, since it isn'r clear for the caller what sideeffects property changes can have. I would just create a method for it, that way, it is more clear for the caller that things can change.

– J. Doe
Nov 29 '18 at 8:13












2 Answers
2






active

oldest

votes


















2














Your isActive property is written incorrectly. It should not be a computed property in the first place. Currently, the getter will just cause infinite recursion and the setter doesn't actually set anything.



The isActive property should be a stored property with a didSet property observer:



@IBInspectable
var isActive: Bool {
didSet {

}
}


Inside didSet, you can just put the last part of commonInit. The first part of commonInit doesn't need to be run every time isActive changes. I recommend you to extract that as a method called updateBorder:



func updateBorder(isActive: Bool) {

if (isActive) {
self.tintColor = ACTIVE_COLOR
self.layer.borderColor = ACTIVE_COLOR.cgColor
} else {
self.tintColor = nil
self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
}

}


And then in didSet, you can just call that:



updateBorder(isActive: isActive)





share|improve this answer































    3














    You should be observing didSet to update the view. In Swift, type names should start with Uppercase e.g ButtonCTAOutlineDark. Please see the fixed class,



    @IBDesignable
    class ButtonCTAOutlineDark: UIButton {

    override init(frame: CGRect) {
    super.init(frame: frame)
    commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    commonInit()
    }

    @IBInspectable var isActive: Bool = false {
    didSet {
    self.commonInit(isActive: self.isActive)
    }
    }

    func commonInit(isActive: Bool = false) {
    self.backgroundColor = .clear
    self.layer.cornerRadius = 4
    self.layer.borderWidth = 1

    if (isActive) {
    self.tintColor = ACTIVE_COLOR
    self.layer.borderColor = ACTIVE_COLOR.cgColor
    } else {
    self.tintColor = nil
    self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
    }
    }
    }





    share|improve this answer
























    • Thanks @Kamran. This helped.

      – hashHb
      Nov 29 '18 at 9:12












    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53532975%2fswift-uibutton-subclass-and-change-color-based-on-variable%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    Your isActive property is written incorrectly. It should not be a computed property in the first place. Currently, the getter will just cause infinite recursion and the setter doesn't actually set anything.



    The isActive property should be a stored property with a didSet property observer:



    @IBInspectable
    var isActive: Bool {
    didSet {

    }
    }


    Inside didSet, you can just put the last part of commonInit. The first part of commonInit doesn't need to be run every time isActive changes. I recommend you to extract that as a method called updateBorder:



    func updateBorder(isActive: Bool) {

    if (isActive) {
    self.tintColor = ACTIVE_COLOR
    self.layer.borderColor = ACTIVE_COLOR.cgColor
    } else {
    self.tintColor = nil
    self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
    }

    }


    And then in didSet, you can just call that:



    updateBorder(isActive: isActive)





    share|improve this answer




























      2














      Your isActive property is written incorrectly. It should not be a computed property in the first place. Currently, the getter will just cause infinite recursion and the setter doesn't actually set anything.



      The isActive property should be a stored property with a didSet property observer:



      @IBInspectable
      var isActive: Bool {
      didSet {

      }
      }


      Inside didSet, you can just put the last part of commonInit. The first part of commonInit doesn't need to be run every time isActive changes. I recommend you to extract that as a method called updateBorder:



      func updateBorder(isActive: Bool) {

      if (isActive) {
      self.tintColor = ACTIVE_COLOR
      self.layer.borderColor = ACTIVE_COLOR.cgColor
      } else {
      self.tintColor = nil
      self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
      }

      }


      And then in didSet, you can just call that:



      updateBorder(isActive: isActive)





      share|improve this answer


























        2












        2








        2







        Your isActive property is written incorrectly. It should not be a computed property in the first place. Currently, the getter will just cause infinite recursion and the setter doesn't actually set anything.



        The isActive property should be a stored property with a didSet property observer:



        @IBInspectable
        var isActive: Bool {
        didSet {

        }
        }


        Inside didSet, you can just put the last part of commonInit. The first part of commonInit doesn't need to be run every time isActive changes. I recommend you to extract that as a method called updateBorder:



        func updateBorder(isActive: Bool) {

        if (isActive) {
        self.tintColor = ACTIVE_COLOR
        self.layer.borderColor = ACTIVE_COLOR.cgColor
        } else {
        self.tintColor = nil
        self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
        }

        }


        And then in didSet, you can just call that:



        updateBorder(isActive: isActive)





        share|improve this answer













        Your isActive property is written incorrectly. It should not be a computed property in the first place. Currently, the getter will just cause infinite recursion and the setter doesn't actually set anything.



        The isActive property should be a stored property with a didSet property observer:



        @IBInspectable
        var isActive: Bool {
        didSet {

        }
        }


        Inside didSet, you can just put the last part of commonInit. The first part of commonInit doesn't need to be run every time isActive changes. I recommend you to extract that as a method called updateBorder:



        func updateBorder(isActive: Bool) {

        if (isActive) {
        self.tintColor = ACTIVE_COLOR
        self.layer.borderColor = ACTIVE_COLOR.cgColor
        } else {
        self.tintColor = nil
        self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
        }

        }


        And then in didSet, you can just call that:



        updateBorder(isActive: isActive)






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 29 '18 at 6:40









        SweeperSweeper

        72.4k1075144




        72.4k1075144

























            3














            You should be observing didSet to update the view. In Swift, type names should start with Uppercase e.g ButtonCTAOutlineDark. Please see the fixed class,



            @IBDesignable
            class ButtonCTAOutlineDark: UIButton {

            override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
            }

            required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
            }

            @IBInspectable var isActive: Bool = false {
            didSet {
            self.commonInit(isActive: self.isActive)
            }
            }

            func commonInit(isActive: Bool = false) {
            self.backgroundColor = .clear
            self.layer.cornerRadius = 4
            self.layer.borderWidth = 1

            if (isActive) {
            self.tintColor = ACTIVE_COLOR
            self.layer.borderColor = ACTIVE_COLOR.cgColor
            } else {
            self.tintColor = nil
            self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
            }
            }
            }





            share|improve this answer
























            • Thanks @Kamran. This helped.

              – hashHb
              Nov 29 '18 at 9:12
















            3














            You should be observing didSet to update the view. In Swift, type names should start with Uppercase e.g ButtonCTAOutlineDark. Please see the fixed class,



            @IBDesignable
            class ButtonCTAOutlineDark: UIButton {

            override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
            }

            required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
            }

            @IBInspectable var isActive: Bool = false {
            didSet {
            self.commonInit(isActive: self.isActive)
            }
            }

            func commonInit(isActive: Bool = false) {
            self.backgroundColor = .clear
            self.layer.cornerRadius = 4
            self.layer.borderWidth = 1

            if (isActive) {
            self.tintColor = ACTIVE_COLOR
            self.layer.borderColor = ACTIVE_COLOR.cgColor
            } else {
            self.tintColor = nil
            self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
            }
            }
            }





            share|improve this answer
























            • Thanks @Kamran. This helped.

              – hashHb
              Nov 29 '18 at 9:12














            3












            3








            3







            You should be observing didSet to update the view. In Swift, type names should start with Uppercase e.g ButtonCTAOutlineDark. Please see the fixed class,



            @IBDesignable
            class ButtonCTAOutlineDark: UIButton {

            override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
            }

            required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
            }

            @IBInspectable var isActive: Bool = false {
            didSet {
            self.commonInit(isActive: self.isActive)
            }
            }

            func commonInit(isActive: Bool = false) {
            self.backgroundColor = .clear
            self.layer.cornerRadius = 4
            self.layer.borderWidth = 1

            if (isActive) {
            self.tintColor = ACTIVE_COLOR
            self.layer.borderColor = ACTIVE_COLOR.cgColor
            } else {
            self.tintColor = nil
            self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
            }
            }
            }





            share|improve this answer













            You should be observing didSet to update the view. In Swift, type names should start with Uppercase e.g ButtonCTAOutlineDark. Please see the fixed class,



            @IBDesignable
            class ButtonCTAOutlineDark: UIButton {

            override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
            }

            required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
            }

            @IBInspectable var isActive: Bool = false {
            didSet {
            self.commonInit(isActive: self.isActive)
            }
            }

            func commonInit(isActive: Bool = false) {
            self.backgroundColor = .clear
            self.layer.cornerRadius = 4
            self.layer.borderWidth = 1

            if (isActive) {
            self.tintColor = ACTIVE_COLOR
            self.layer.borderColor = ACTIVE_COLOR.cgColor
            } else {
            self.tintColor = nil
            self.layer.borderColor = UIColor(red:0.69, green:0.72, blue:0.77, alpha:1.0).cgColor
            }
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 29 '18 at 6:39









            KamranKamran

            7,18821129




            7,18821129













            • Thanks @Kamran. This helped.

              – hashHb
              Nov 29 '18 at 9:12



















            • Thanks @Kamran. This helped.

              – hashHb
              Nov 29 '18 at 9:12

















            Thanks @Kamran. This helped.

            – hashHb
            Nov 29 '18 at 9:12





            Thanks @Kamran. This helped.

            – hashHb
            Nov 29 '18 at 9:12


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53532975%2fswift-uibutton-subclass-and-change-color-based-on-variable%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Lallio

            Futebolista

            Jornalista