2017-11-17 9 views
0

チェックマークのようなUIButtonサブクラスを作成しました。ここでカスタムUIButton @IBDesignable

クラスです:

import UIKit 

@IBDesignable 
class CheckedButton: UIButton { 

    // MARK: - Properties 
    @IBInspectable var checked: Bool = false { 
     didSet { 
      // Toggle the check/uncheck images 
      updateImage() 
     } 
    } 


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

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

    private func setup() { 
     updateImage() 
     self.addTarget(self, action: #selector(tapped), for: .touchUpInside) 
    } 

    private func updateImage() { 
     let image = checked ? UIImage(named: "checked") : UIImage(named: "unchecked") 
     self.setImage(image, for: .normal) 
    } 

    /// Called each time the button is tapped, and toggles the checked property 
    @objc private func tapped() { 
     checked = !checked 
     print("New value: \(checked)") 
    } 
} 

私は@IBInspectableとしてcheckedプロパティを設定しているので、私はIBでそれを参照してください。 IBInspectable

奇妙なことがある:

  • 場合私はこのプロパティをdefaultとしました。ストーリーボードに正しく表示されています。

uncheck

  • が、私はインスペクタinthe onまたはoffのいずれかを選択した場合、画面が正しく更新されません。

empty

クラスが@IBDesignableマークされているように、私は、ボタンの外観はインスペクタ]タブでは、このプロパティに設定された値に応じてIBに更新するよう期待します。 手掛かりがありますか?

private func updateImage() { 
    let image = checked ? UIImage.image(name: "checked", self) : UIImage(name: "unchecked", self) 
    setImage(image, for: .normal) 
} 

また、UIButtonクラスがチェックしている状態、あなたが作成することなく使用することができます。

extension UIImage { 
    public static func image(name: String, _ sender: UIView?) -> UIImage? { 
     #if TARGET_INTERFACE_BUILDER 
      if let sender = sender { 
       let bundle = Bundle(for: sender.classForCoder) 
       return UIImage(named: name, in: bundle, compatibleWith: sender.traitCollection) 
      } else { 
       return UIImage(named: name) 
      } 
     #else 
      return UIImage(named: name) 
     #endif 
    } 
} 

ご例えば:

答えて

1

UIimage(名前付き:)メソッドはメインバンドルを使用しますが、Interf ace Builderはリソースを別の方法でロードします。

これを試してみてください:

UIImage(という名前を: "確認"、中:バンドル、compatibleWith:ゼロ)あなたの答えのための

@IBDesignable 

class CheckedButton: UIButton { 

// MARK: - Properties 
@IBInspectable var checked: Bool = false { 
    didSet { 
     // Toggle the check/uncheck images 
     updateImage() 
    } 
} 


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

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

override func prepareForInterfaceBuilder() { 
    super.prepareForInterfaceBuilder() 
    setup() 
} 

internal func setup() { 
    self.addTarget(self, action: #selector(tapped), for: .touchUpInside) 
} 

private func updateImage() { 
    let bundle = Bundle(for: CheckedButton.self) 
    let image = checked ? UIImage(named: "checked", in: bundle, compatibleWith:nil) : UIImage(named: "unchecked", in: bundle, compatibleWith:nil) 
    self.setBackgroundImage(image, for: .normal) 
} 

/// Called each time the button is tapped, and toggles the checked property 
@objc private func tapped() { 
    checked = !checked 
    print("New value: \(checked)") 
} 

just like this

-1

私の提案は、資産から画像を取得するために他のカスタム関数を使用しています独自のサブクラス:

let btn = UIButton(type: .custom) 
btn.setImage(UIImage.image(name: "unchecked", self), for: .normal) 
btn.setImage(UIImage.image(name: "checked", self), for: .selected) 

btn.isSelected = true // change button state between checked and unchecked 
+0

感謝。しかし、あなたのエクステンションは、資産ライブラリにあるいくつかの画像を取得するのがかなり複雑になります(これは、今日のAppleが推奨する方法です)。また、私はこのボタンを複数回使用するので、このボタンをサブクラス化する必要があります。同じ画像設定を何度も繰り返したくはありません。 –

関連する問題