나는라는 클래스가 MyClass
의 서브 클래스입니다 UIView
제가으로 초기화 할 것인지, XIB
파일. xib 파일을 사용 하여이 클래스를 초기화하는 방법을 잘 모르겠습니다.View.xib
class MyClass: UIView {
// what should I do here?
//init(coder aDecoder: NSCoder) {} ??
}
나는라는 클래스가 MyClass
의 서브 클래스입니다 UIView
제가으로 초기화 할 것인지, XIB
파일. xib 파일을 사용 하여이 클래스를 초기화하는 방법을 잘 모르겠습니다.View.xib
class MyClass: UIView {
// what should I do here?
//init(coder aDecoder: NSCoder) {} ??
}
답변:
이 코드를 테스트했으며 훌륭하게 작동합니다.
class MyClass: UIView {
class func instanceFromNib() -> UIView {
return UINib(nibName: "nib file name", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as UIView
}
}
뷰를 초기화하고 아래와 같이 사용하십시오.
var view = MyClass.instanceFromNib()
self.view.addSubview(view)
또는
var view = MyClass.instanceFromNib
self.view.addSubview(view())
스위프트 업데이트> = 3.x 및 스위프트> = 4.x
class func instanceFromNib() -> UIView {
return UINib(nibName: "nib file name", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
}
var view = MyClass.instanceFromNib()
& self.view.addSubview(view)
반대로 var view = MyClass.instanceFromNib
& self.view.addSubview(view())
. 답변을 개선하기위한 작은 제안 :)
Sam의 솔루션은 다른 번들을 고려하지 않았음에도 불구하고 이미 훌륭합니다 (NSBundle : forClass가 구출됩니다). 코드를 입력하는 수동 로딩이 필요합니다.
Xib Outlets, 다른 번들 (프레임 워크에서 사용)을 완벽하게 지원하고 스토리 보드에서 멋진 미리보기를 얻으려면 다음을 시도하십시오.
// NibLoadingView.swift
import UIKit
/* Usage:
- Subclass your UIView from NibLoadView to automatically load an Xib with the same name as your class
- Set the class name to File's Owner in the Xib file
*/
@IBDesignable
class NibLoadingView: UIView {
@IBOutlet weak var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
nibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
nibSetup()
}
private func nibSetup() {
backgroundColor = .clearColor()
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
view.translatesAutoresizingMaskIntoConstraints = true
addSubview(view)
}
private func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: String(self.dynamicType), bundle: bundle)
let nibView = nib.instantiateWithOwner(self, options: nil).first as! UIView
return nibView
}
}
평소와 같이 xib를 사용하십시오. 즉, Outlet을 파일 소유자에 연결하고 파일 소유자 클래스를 자신의 클래스로 설정하십시오.
사용법 : NibLoadingView에서 자신의 View 클래스를 서브 클래스 화 하고 Xib 파일에서 클래스 이름을 File 's Owner 로 설정 하십시오.
더 이상 추가 코드가 필요하지 않습니다.
크레디트 기한이있는 크레디트 : GH에서 DenHeadless의 사소한 변경으로이를 포크했습니다. 내 요지 : https://gist.github.com/winkelsdorf/16c481f274134718946328b6e2c9a4d8
nibSetup
로부터하는 init?(coder:)
매립 경우 무한 재귀 발생할 NibLoadingView
XIB있다.
.clearColor()
스토리 보드에서로드 한 후 배경색을 재정의하는 nibSetup () 때문일 수 있습니다. 그러나 인스턴스화 후 코드로 수행하면 작동합니다. 어쨌든 더 우아한 접근 방식은 프로토콜 기반 접근 방식입니다. github.com/AliSoftware/Reusable 링크가 있습니다 . UITableViewCells와 관련하여 비슷한 접근법을 사용하고 있습니다 (실제로 유용한 프로젝트를 발견하기 전에 구현했습니다). hth!
Swift 2.0부터는 프로토콜 확장을 추가 할 수 있습니다. 내 의견으로는, 반환 유형이 Self
아닌 UIView
이므로 호출자가 뷰 클래스로 캐스팅 할 필요 가 없기 때문에 더 나은 접근 방식 입니다.
import UIKit
protocol UIViewLoading {}
extension UIView : UIViewLoading {}
extension UIViewLoading where Self : UIView {
// note that this method returns an instance of type `Self`, rather than UIView
static func loadFromNib() -> Self {
let nibName = "\(self)".characters.split{$0 == "."}.map(String.init).last!
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiateWithOwner(self, options: nil).first as! Self
}
}
var myView = nib.instantiate... as! myViewType
Swift 3
(XCode 8.0 베타 6)을 사용하여 프로젝트에서 열어 테스트 한 코드를 문제없이 게시했습니다 . 오타가있었습니다 Swift 2
. 이 답변이 좋을 때 왜 또 다른 대답이되어야하며 사용자는 XC8을 사용할 때 변경 사항이 무엇인지 검색하는 것이 좋습니다
그리고 이것은 스위프트 3.0에 프레드릭의 답변입니다
/*
Usage:
- make your CustomeView class and inherit from this one
- in your Xib file make the file owner is your CustomeView class
- *Important* the root view in your Xib file must be of type UIView
- link all outlets to the file owner
*/
@IBDesignable
class NibLoadingView: UIView {
@IBOutlet weak var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
nibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
nibSetup()
}
private func nibSetup() {
backgroundColor = .clear
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.translatesAutoresizingMaskIntoConstraints = true
addSubview(view)
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let nibView = nib.instantiate(withOwner: self, options: nil).first as! UIView
return nibView
}
}
xib에서 뷰를로드하는 보편적 인 방법 :
예:
let myView = Bundle.loadView(fromNib: "MyView", withType: MyView.self)
이행:
extension Bundle {
static func loadView<T>(fromNib name: String, withType type: T.Type) -> T {
if let view = Bundle.main.loadNibNamed(name, owner: nil, options: nil)?.first as? T {
return view
}
fatalError("Could not load view with type " + String(describing: type))
}
}
스위프트 3 답변 : 필자의 경우 사용자 정의 클래스에 수정할 수있는 콘센트가 필요했습니다.
class MyClassView: UIView {
@IBOutlet weak var myLabel: UILabel!
class func createMyClassView() -> MyClass {
let myClassNib = UINib(nibName: "MyClass", bundle: nil)
return myClassNib.instantiate(withOwner: nil, options: nil)[0] as! MyClassView
}
}
.xib에있을 때 사용자 정의 클래스 필드가 MyClassView인지 확인하십시오. 파일 소유자를 귀찮게하지 마십시오.
또한 MyClassView의 콘센트를 레이블에 연결해야합니다.
그것을 인스턴스화하려면 :
let myClassView = MyClassView.createMyClassView()
myClassView.myLabel.text = "Hello World!"
스위프트 4
내 경우에는 데이터를 해당 사용자 정의보기로 전달해야하므로보기를 인스턴스화하는 정적 함수를 만듭니다.
UIView 확장 만들기
extension UIView {
class func initFromNib<T: UIView>() -> T {
return Bundle.main.loadNibNamed(String(describing: self), owner: nil, options: nil)?[0] as! T
}
}
MyCustomView 작성
class MyCustomView: UIView {
@IBOutlet weak var messageLabel: UILabel!
static func instantiate(message: String) -> MyCustomView {
let view: MyCustomView = initFromNib()
view.messageLabel.text = message
return view
}
}
.xib 파일에서 사용자 정의 클래스를 MyCustomView로 설정하십시오. 필요에 따라 콘센트를 연결하십시오.
보기 인스턴스화
let view = MyCustomView.instantiate(message: "Hello World.")
override func draw(_ rect: CGRect)
{
AlertView.layer.cornerRadius = 4
AlertView.clipsToBounds = true
btnOk.layer.cornerRadius = 4
btnOk.clipsToBounds = true
}
class func instanceFromNib() -> LAAlertView {
return UINib(nibName: "LAAlertView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! LAAlertView
}
@IBAction func okBtnDidClicked(_ sender: Any) {
removeAlertViewFromWindow()
UIView.animate(withDuration: 0.4, delay: 0.0, options: .allowAnimatedContent, animations: {() -> Void in
self.AlertView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
}, completion: {(finished: Bool) -> Void in
self.AlertView.transform = CGAffineTransform.identity
self.AlertView.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
self.AlertView.isHidden = true
self.AlertView.alpha = 0.0
self.alpha = 0.5
})
}
func removeAlertViewFromWindow()
{
for subview in (appDel.window?.subviews)! {
if subview.tag == 500500{
subview.removeFromSuperview()
}
}
}
public func openAlertView(title:String , string : String ){
lblTital.text = title
txtView.text = string
self.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)
appDel.window!.addSubview(self)
AlertView.alpha = 1.0
AlertView.isHidden = false
UIView.animate(withDuration: 0.2, animations: {() -> Void in
self.alpha = 1.0
})
AlertView.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
UIView.animate(withDuration: 0.3, delay: 0.2, options: .allowAnimatedContent, animations: {() -> Void in
self.AlertView.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
}, completion: {(finished: Bool) -> Void in
UIView.animate(withDuration: 0.2, animations: {() -> Void in
self.AlertView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
})
})
}