我正在构建一个天气应用程序作为初学者项目。假设我想要一个自定义视图,其中包含许多UILabel的温度,湿度,降水等。这个想法是,这个自定义UIView将被用于用户保存的每个城市多次。如果用户保存了3个城市,则自定义视图将包含3个实例。
最好的方法是什么?我正在尝试将UIView子类化。最初我覆盖了drawRect(rect:CGRect)并在那里定义了我的UILabels。那感觉不对劲。在我尝试更新NSURLSession上的完成处理程序中的标签文本之后,它将不会得到alloc / inited。
或者我应该覆盖init(),这使我这样做:
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
我不知道这意味着什么。然后,当我尝试在根VC上使用框架初始化时,我不得不做这样的事情。
override init(frame: CGRect) { super.init(frame: frame) }
有人能指引我完成最好的方法吗?我有类似下面的内容但是当我尝试将UILabels添加到自定义类的子视图时,我得到了一个零值。
class ViewTemplate: UIView {
var tempLabel: UILabel!
var humidityLabel: UILabel!
override init () {
tempLabel = UILabel()
tempLabel.frame = CGRectMake(halfScreenWidth - 130, 120, 260, 130)
tempLabel.textColor = UIColor.whiteColor()
tempLabel.backgroundColor = UIColor.clearColor()
// similar stuff for humidityLabel
super.init()
addSubview(tempLabel)
}
override init(frame: CGRect) { super.init(frame: frame) }
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
如果不太确定nil来自哪里。但最重要的是,我正在寻找这样做的最佳实践。 谢谢!
答案 0 :(得分:1)
用于创建个人视图:
在awakeFromNib()方法中实例化它们。 如果文本是标签,请务必设置文本的默认值。否则,它们会在实例化时显示为nil,并且您的应用程序将崩溃。
导入UIKit
类MyView:UIView {
@IBOutlet weak var templabel:UILabel!
覆盖func awakeFromNib(){ super.awakeFromNib() self.tempLabel.text =“95度”
}
加载到viewcontroller:
1a上。创建一个实现UIScrollView的viewcontroller。 1B。在故事板中放置UIScrollview并将其连接到该视图控制器
class MyWeatherViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet var scrollView: UIScrollView!
2a上。在ViewDidLoad中,创建您要创建的UIView的实例。单独填充它们。 2B。在ViewDidLoad中,将scrollview宽度设置为单个View的宽度。将高度设置为单个View的高度*您希望显示的视图数
var view1: MyView = MyView()
var view2: MyView = MyView()
let viewArray[MyView!] = [view1, view2]
for items in viewArray {
var frame = scrollView.bounds
//Set the origin of the views
frame.origin.x = 0.0
frame.origin.y = frame.size.height * items
//create a view out of the object provided, define it's frame, and add to scrollview
let viewToAdd = viewArray[items].view
newPageView.frame = frame
scrollView.addSubview(viewToAdd)
//设置要显示的标签。您必须在将负载加载到滚动视图后执行此操作 viewArray [items] .tempLabel.text =“105度” }
请记住,您需要设置另一个数据模型来保存要显示的信息。我建议创建一个包含您想要显示的信息的数组,这样您就可以使用您想要设置的所有标签来执行viewArray [items] .tempLabel.text = tempArray [items]。
这应该垂直对齐它们以滚动和查看所有项目的能力。
这也可以根据用户保存的城市动态决定要添加的视图数量。只需修改逻辑即可阅读用户拥有的许多城市等。
答案 1 :(得分:0)
你走在正确的轨道上。
let
而不是var
的常量,因为您应该始终拥有这些标签。init(frame: CGRect)
方法。再次,看起来你已经开始这样了。您应该覆盖init(frame: CGRect)
的原因是init()
,因为init()
只是调用init(frame: CGRectZero)
。如果你只实现init()
,那么你的一些属性可能不会被初始化(尽管这对Swift来说不是一个问题,因为你可以将属性声明为常量,因此编译器会抛出错误)。在您的初始化程序中,您需要初始化所有标签&在致电super.init(frame)
之前设置它们。调用super.init(frame)
方法后,您应该将标签添加为self的子视图。layoutSubviews()
。您可以使用此方法执行所有大小调整和布局子视图。我这样做的一切都是我最熟悉的。如果你正在使用AutoLayout,我认为最好的做法是在课程的初始化程序中应用这些约束,因为它们只需要设置一次。sizeThatFits()
。这将确保在调用sizeToFit()
时,您的视图始终是正确的大小。这不仅适用于UIView
,而且适用于它的任何子类。
答案 2 :(得分:0)
您可以使用UIViewController扩展并初始化采用UIView的UIView函数。您可以在项目中的任何地方使用它。
extension UIViewController {
func setView(_ view: UIView){
view.backgroundColor = UIColor()
view.layer.cornerRadius = 5.0
// customize your view
}
}
然后:声明您在Controller中查看并在viewDidLoad()上调用该函数时传递它
let myView = UIView()
setView(myView)