我想知道在确定一个类必须是UIview或UIviewcontroller时的最佳实践是什么。
我正在开发一个在单个Viewcontroller中一次使用多个类和视图的应用程序。我有一个动态创建按钮的视图。该视图与ViewController中的许多其他视图并存。由于此视图实现了很多行代码,因此我将其置于单独的类中。那么问题是:应该扩展UiView还是UIViewcontroller?
此视图将具有一些属性,例如填充,可用尺寸等。这些属性取决于其子类ViewViewler的自动布局锚点。如果我使用UIview,这些将不会在Init上实例化。
为什么我应该选择一个?
TagController类:UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var buttons : [UIButton: String]?
var sidePadding = CGFloat(15);
var topPadding = CGFloat(15);
var spacing = CGFloat(10);
var availableHeight : CGFloat!
var availableWidth : CGFloat!
func createButton (title: String) -> UIButton {
let maxWidth : CGFloat = 180;
let button = UIButton();
button.setTitle(title, for: .normal)
button.titleLabel?.font = UIFont(name: "Avenir-Light", size: 15.0)
button.translatesAutoresizingMaskIntoConstraints = false;
self.addSubview(button)
button.frame = CGRect(x:0,y:0,width:button.intrinsicContentSize.width, height: button.intrinsicContentSize.height)
if button.frame.width > maxWidth { button.widthAnchor.constraint(equalToConstant: maxWidth).isActive = true }
button.backgroundColor = .blue
// button.addTarget(self, action: #selector(self.onButtonPresed(_:)), for: .touchUpInside);
return button;
}
public func addButton(name: String) {
let button = createButton(title: name)
setConstriants(button: button)
}
private func setConstriants(button: UIButton) {
for label in buttons {
if totalHeight + 50 > availableHeight { createMoreButton(topPadding); break };
let button = createButton(buttonText: label)
let buttonWidth = button.intrinsicContentSize.width;
let buttonHeight = button.intrinsicContentSize.height;
if buttonWidth > availableWidth {
button.widthAnchor.constraint(equalToConstant: availableWidth - sidePadding).isActive = true;
}
if rowLength == 0 && rowCount == 0
{
setFirstButtonConstraint(button: button, totalHeight: totalHeight, sidePadding: sidePadding)
rowLength += buttonWidth + sidePadding // FIX annoying first row image overlap
}
else if rowLength + buttonWidth + padding < availableWidth
{
setConstraint(button: button, lastButton: lastButton, totalHeight: totalHeight, padding: padding)
rowLength += buttonWidth + padding;
}
else
{
totalHeight += buttonHeight + padding
rowLength = buttonWidth + sidePadding;
rowCount += 1;
setNewRowConstraint(button: button, totalHeight:totalHeight , sidePadding: sidePadding)
}
indexOfLastButton += 1;
lastButton = button
displayedButtons.append(button)
print("Buttons displayed \(displayedButtons.count)")
}
pulsate_buttons(duration: 0.1)
}
private func removeDisplayedButtons() {
for _ in 0...displayedButtons.count {
displayedButtons.popLast()?.removeFromSuperview();
}
};
private func setFirstButtonConstraint(button: UIButton, totalHeight: CGFloat, sidePadding: CGFloat) {
button.topAnchor.constraint(equalTo: self.topAnchor, constant: totalHeight).isActive = true;
button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: sidePadding + 5).isActive = true;
}
private func setConstraint(button: UIButton, lastButton: UIButton, totalHeight: CGFloat, padding:CGFloat) {
button.leadingAnchor.constraint(equalTo: lastButton.trailingAnchor, constant: padding).isActive = true;
button.topAnchor.constraint(equalTo: self.topAnchor, constant: totalHeight).isActive = true;
}
private func setNewRowConstraint(button: UIButton, totalHeight: CGFloat, sidePadding: CGFloat) {
button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: sidePadding).isActive = true;
button.topAnchor.constraint(equalTo: self.topAnchor, constant: totalHeight).isActive = true;
}
private func createMoreButton(_ topPadding: CGFloat) {
if moreButton != nil { return }
let btn = UIButton()
btn.setImage(UIImage(named: "suggestionCloud_more_button.png"), for: .normal)
let buttonText = "Moooar.."
btn.setTitle(buttonText, for: .normal)
btn.setTitleColor(.black, for: .normal)
btn.titleLabel?.font = UIFont(name: "Avenir-Light", size: 15.0)
self.addSubview(btn)
moreButton = btn
btn.frame = CGRect(x: (self.frame.size.width/2 - 20), y: self.frame.size.height * 0.85, width: 40, height: 15)
btn.addTarget(self, action: #selector(showMoreButtons(_:)), for: .touchUpInside)
}
@objc func showMoreButtons(_: UIButton) {
pulsate_view(duration: 0.1)
if indexOfLastButton == labelStore.count { indexOfLastButton = 0; return createLayout(buttons : labelStore)}
let buttonsToBeDisplayed : [String] = Array(labelStore[indexOfLastButton...])
createLayout(buttons: buttonsToBeDisplayed)
}
答案 0 :(得分:0)
我喜欢这样想:UIView
托管和管理离散内容,而UIViewController
托管和管理由许多离散内容组成的应用程序内容。
您可以从桌面应用程序来思考它,其中“窗口”是UIViewController
,而此窗口的元素(按钮,工具栏等)是UIViews
(您也可以在UIViewControllers
内托管其他UIViewController
。
通常,UIViews
不应决定应用程序导航逻辑,而应将其推迟到UIViewController
。
简单来说,如果某些内容以模态呈现或占据整个屏幕,则可能是UIViewController
。
传统上,Apple采用MVC范例(模型/视图/控制器)。如果您的内容是模型(一个人的出生日期,您拍摄的照片),则在其中显示视图,而Controller在内容管理(持久性,检索)和内容的显示之间进行调解。>
顺便说一句:在UIStackView
中查找您的按钮行。
奖金:如何为以编程方式实例化的UIView
使用自定义初始化程序。
如果仅通过编程方式创建了每个视图(并且未通过界面生成器实例化),则可以为其定义所需的初始化程序:
class MyView: UIView {
var required: Bool
var anotherRequiredVar: String
required init(frame: CGRect, something: Bool, somethingElse: String) {
required = something
anotherRequiredVar = somethingElse
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init with coder not implemented")
}
}
在此示例中,init?(coder)方法引发异常。取消存档Storyboard或Nib内容时,此初始值设定程序由界面构建器运行。由于您不需要它,因此可以抛出致命错误(因为必须实现该方法才能使编译成功)。