programing

스위프트 하위 클래스 UIView

megabox 2023. 8. 27. 09:03
반응형

스위프트 하위 클래스 UIView

하위 클래스를 원합니다.UIView로그인과 같은 보기를 표시합니다.나는 이것을 Objective-C에서 만들었지만, 지금은 Swift에 이식하고 싶습니다.스토리보드를 사용하지 않기 때문에 모든 UI를 코드로 만듭니다.

하지만 첫 번째 문제는 제가 실행해야 한다는 것입니다.initWithCoder호출되지 않기 때문에 기본 구현을 지정했습니다.합니다. 저는 이제프충돌다니합실면행하을램그를 실행해야 하기 입니다. 왜냐하면 구현해야 하기 때문입니다.initWithFrame뿐만 아니라.이제 알겠어요.

override init() {
    super.init()
    println("Default init")
}

override init(frame: CGRect) {
    super.init(frame: frame)
    println("Frame init")
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    println("Coder init")
}

내 질문은 내 텍스트 필드 등을 어디에 만들어야 하는가 하는 것입니다.그리고 프레임과 코더를 구현하지 않는다면 어떻게 이것을 "숨길" 수 있습니까?

저는 보통 이런 걸 하는데, 좀 장황합니다.

class MyView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        addBehavior()
    }

    convenience init() {
        self.init(frame: CGRect.zero)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("This class does not support NSCoding")
    }

    func addBehavior() {
        print("Add all the behavior here")
    }
}



let u = MyView(frame: CGRect.zero)
let v = MyView()

(편집: 이니셜라이저 간의 관계가 더 명확하도록 답변을 편집했습니다)

이것은 더 간단합니다.

override init (frame : CGRect) {
    super.init(frame : frame)
    // Do what you want.
}

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

사용자 지정 UIView 하위 클래스 예제

저는 보통 스토리보드나 닙을 사용하지 않고 iOS 앱을 만듭니다.질문에 답하기 위해 배운 몇 가지 기술을 공유하겠습니다.

 

원하지 않는 항목 숨기기init

의 첫 입니다.UIView원하지 않는 초기화자를 숨깁니다.는 "UI 하위 클래스에서 스토리보드 Nib 특정 이니셜라이저를 숨기는 방법"에 대한 답변에서 이 접근 방식에 대해 자세히 설명했습니다.참고: 이 접근 방식은 다음을 사용하지 않을 것으로 가정합니다.BaseView또는 의도적으로 앱을 중단시킬 수 있기 때문에 스토리보드나 닙에 있는 하위 항목입니다.

class BaseView: UIView {

    // This initializer hides init(frame:) from subclasses
    init() {
        super.init(frame: CGRect.zero)
    }

    // This attribute hides `init(coder:)` from subclasses
    @available(*, unavailable)
    required init?(coder aDecoder: NSCoder) {
        fatalError("NSCoding not supported")
    }
}

정의 는 UIView에서 .BaseView이니셜라이저에서 super.init()를 호출해야 합니다.를 구현할 가 없습니다.init(coder:)이는 아래 예제에서 확인할 수 있습니다.

 

UI 텍스트 필드 추가

외부에서 참조되는 하위 보기에 대해 저장된 속성을 만듭니다.init방법.의 경우 으로 그렇게 .UITextField의 경우 일반적으로 그렇게 합니다.를 다음과하는 것을 합니다.let textField = UITextField().

는 사용자 까지는 UI를 사용자 정의 뷰의 목록에 할 수 .addSubview(_:)이는 아래 예제에서 확인할 수 있습니다.

 

자동 레이아웃을 사용하지 않는 프로그래밍 방식

크기와 위치를 설정하지 않으면 UI 텍스트 필드가 표시되지 않습니다.는 종종 layoutSubviews 메서드 내에서 (자동 레이아웃을 사용하지 않고) 코드로 레이아웃을 수행합니다.layoutSubviews()는 초기 및 크기 조정 이벤트가 발생할 때마다 호출됩니다.이렇게 하면 사용자 정의 보기 크기에 따라 레이아웃을 조정할 수 있습니다.예를 들어, CustomView가 다양한 크기의 iPhone 및 iPad에 전체 너비로 표시되고 회전을 위해 조정되는 경우, 많은 초기 크기를 수용하고 동적으로 크기를 조정해야 합니다.

다음을 참조할 수 있습니다.frame.height그리고.frame.width에 내에layoutSubviews()CustomView의 치수를 참조할 수 있습니다.이는 아래 예제에서 확인할 수 있습니다.

 

UIView 하위 클래스 예제

UItextField를 가 없는 하는 사용자 정의 입니다.init?(coder:).

class CustomView: BaseView {

    let textField = UITextField()

    override init() {
        super.init()

        // configure and add textField as subview
        textField.placeholder = "placeholder text"
        textField.font = UIFont.systemFont(ofSize: 12)
        addSubview(textField)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        // Set textField size and position
        textField.frame.size = CGSize(width: frame.width - 20, height: 30)
        textField.frame.origin = CGPoint(x: 10, y: 10)
    }
}

 

자동 레이아웃을 사용한 프로그래밍 방식 레이아웃

코드에서 자동 레이아웃을 사용하여 레이아웃을 구현할 수도 있습니다.제가 자주 하지 않기 때문에, 저는 본보기를 보여주지 않을 것입니다.스택 오버플로 및 인터넷의 다른 곳에서 코드에서 자동 레이아웃을 구현하는 예를 찾을 수 있습니다.

 

프로그래밍 방식 레이아웃 프레임워크

코드에서 레이아웃을 구현하는 오픈 소스 프레임워크가 있습니다.제가 관심은 있지만 시도해보지 않은 것 중 하나는 LayoutKit입니다.개발팀 링크드인이 작성했습니다.Github 저장소에서: "자동 레이아웃이 스크롤 가능한 뷰에서 복잡한 뷰 계층 구조를 수행하기에 충분하지 않다는 것을 발견했기 때문에 LinkedIn이 LayoutKit를 만들었습니다."

 

왜넣요를 넣습니까?fatalErrorinit(coder:)

닙에서 ▁param▁the▁▁and▁▁be▁by▁you▁▁thatclass▁notization▁could▁differentiv▁uboard▁or▁initial,▁require▁a▁initial초iv▁nib▁called▁storyw▁might▁be▁will다있es도스수▁creating할서▁sub입기▁never▁in▁that른화사다를토자니습▁used로init(coder:)방법. coder (coder:)fatalError스토리보드/비디오판에 실수로 사용될 경우 매우 혼란스러운 문제가 발생할 수 있습니다.치명적인 오류는 이러한 의도를 주장합니다.

required init?(coder aDecoder: NSCoder) {
    fatalError("NSCoding not supported")
}

하위 클래스가 코드로 생성되었는지 스토리보드/nib로 생성되었는지에 관계없이 하위 클래스가 생성되었을 때 일부 코드를 실행하려면 다음과 같은 작업을 수행할 수 있습니다(Jeff Gu Kang의 답변 기준).

class CustomView: UIView {
    override init (frame: CGRect) {
        super.init(frame: frame)
        initCommon()
    }

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

    func initCommon() {
        // Your custom initialization code
    }
}

UI뷰는 인터페이스 빌더/스토리보드 또는 코드로 작성할 수 있어야 합니다.저는 그것이 유용하다고 생각합니다.setup설정 코드의 중복을 줄이는 방법입니다.

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

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

    func setup () {
        backgroundColor = .red
    }
}

Swift 4.0, 만약 당신이 xib 파일에서 뷰를 사용하고 싶다면, 이것은 당신을 위한 것입니다.UIView의 CustomCalloutView 클래스 하위 클래스를 만들었습니다.xib 파일을 만들고 IB에서 파일 소유자를 선택한 다음 Attribute inspector set class name to CustomCalloutView를 선택하고 클래스에 아웃렛을 만듭니다.

    import UIKit
    class CustomCalloutView: UIView {

        @IBOutlet var viewCallout: UIView! // This is main view

        @IBOutlet weak var btnCall: UIButton! // subview of viewCallout
        @IBOutlet weak var btnDirection: UIButton! // subview of viewCallout
        @IBOutlet weak var btnFavourite: UIButton! // subview of viewCallout 

       // let nibName = "CustomCalloutView" this is name of xib file

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

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

        func nibSetup() {
            Bundle.main.loadNibNamed(String(describing: CustomCalloutView.self), owner: self, options: nil)
            guard let contentView = viewCallout else { return } // adding main view 
            contentView.frame = self.bounds //Comment this line it take default frame of nib view
           // custom your view properties here
            self.addSubview(contentView)
        }
    }

이제 추가합니다.

    let viewCustom = CustomCalloutView.init(frame: CGRect.init(x: 120, y: 120, 50, height: 50))
    self.view.addSubview(viewCustom)

다음은 일반적으로 하위 클래스(UIView)를 구축하는 방법의 예입니다.내용을 변수로 사용하여 나중에 다른 클래스에서 액세스하고 수정할 수 있습니다.자동 레이아웃 및 콘텐츠 추가 방법도 보여드렸습니다.

예를 들어 ViewController에서 이 뷰가 InViewDidLoad()로 초기화되어 있습니다. 이 뷰는 뷰가 표시될 때 한 번만 호출되기 때문입니다. 여기서 합니다.addContentToView()그리고 나서.activateConstraints()내용을 작성하고 제약 조건을 설정합니다.나중에 ViewController(보기 컨트롤러)에서 버튼을 빨간색으로 표시하려면 해당 ViewController(보기 컨트롤러)의 특정 기능을 사용합니다.과 같은 것: 다과같은것음:func tweaksome(){ self.customView.someButton.color = UIColor.red}

class SomeView: UIView {


var leading: NSLayoutConstraint!
var trailing: NSLayoutConstraint!
var bottom: NSLayoutConstraint!
var height: NSLayoutConstraint!


var someButton: UIButton = {
    var btn: UIButton = UIButton(type: UIButtonType.system)
    btn.setImage(UIImage(named: "someImage"), for: .normal)
    btn.translatesAutoresizingMaskIntoConstraints = false
    return btn
}()

var btnLeading: NSLayoutConstraint!
var btnBottom: NSLayoutConstraint!
var btnTop: NSLayoutConstraint!
var btnWidth: NSLayoutConstraint!

var textfield: UITextField = {
    var tf: UITextField = UITextField()
    tf.adjustsFontSizeToFitWidth = true
    tf.placeholder = "Cool placeholder"
    tf.translatesAutoresizingMaskIntoConstraints = false
    tf.backgroundColor = UIColor.white
    tf.textColor = UIColor.black
    return tf
}()
var txtfieldLeading: NSLayoutConstraint!
var txtfieldTrailing: NSLayoutConstraint!
var txtfieldCenterY: NSLayoutConstraint!

override init(frame: CGRect){
    super.init(frame: frame)
    self.translatesAutoresizingMaskIntoConstraints = false
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    //fatalError("init(coder:) has not been implemented")
}



/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
    // Drawing code

}
*/
func activateConstraints(){
    NSLayoutConstraint.activate([self.btnLeading, self.btnBottom, self.btnTop, self.btnWidth])
    NSLayoutConstraint.activate([self.txtfieldCenterY, self.txtfieldLeading, self.txtfieldTrailing])
}

func addContentToView(){
    //setting the sizes
    self.addSubview(self.userLocationBtn)

    self.btnLeading = NSLayoutConstraint(
        item: someButton,
        attribute: .leading,
        relatedBy: .equal,
        toItem: self,
        attribute: .leading,
        multiplier: 1.0,
        constant: 5.0)
    self.btnBottom = NSLayoutConstraint(
        item: someButton,
        attribute: .bottom,
        relatedBy: .equal,
        toItem: self,
        attribute: .bottom,
        multiplier: 1.0,
        constant: 0.0)
    self.btnTop = NSLayoutConstraint(
        item: someButton,
        attribute: .top,
        relatedBy: .equal,
        toItem: self,
        attribute: .top,
        multiplier: 1.0,
        constant: 0.0)
    self.btnWidth = NSLayoutConstraint(
        item: someButton,
        attribute: .width,
        relatedBy: .equal,
        toItem: self,
        attribute: .height,
        multiplier: 1.0,
        constant: 0.0)        


    self.addSubview(self.textfield)
    self.txtfieldLeading = NSLayoutConstraint(
        item: self.textfield,
        attribute: .leading,
        relatedBy: .equal,
        toItem: someButton,
        attribute: .trailing,
        multiplier: 1.0,
        constant: 5)
    self.txtfieldTrailing = NSLayoutConstraint(
        item: self.textfield,
        attribute: .trailing,
        relatedBy: .equal,
        toItem: self.doneButton,
        attribute: .leading,
        multiplier: 1.0,
        constant: -5)
    self.txtfieldCenterY = NSLayoutConstraint(
        item: self.textfield,
        attribute: .centerY,
        relatedBy: .equal,
        toItem: self,
        attribute: .centerY,
        multiplier: 1.0,
        constant: 0.0)
}
}

언급URL : https://stackoverflow.com/questions/27056864/swift-subclass-uiview

반응형