iOS with Swift 的代码结构,什么去哪里,所有代码



所以我是 iOS 新手,但对 Android 很熟悉,我开始掌握大多数东西的要点,但我很难理解什么去哪里,为什么是这样......

当你只使用故事板时,实现MVC模式(或任何其他视图分离模式)很容易,但是当你在代码中制作所有内容时,我觉得它变得有点混乱。

假设我有一个视图控制器,其父视图包含子视图,该视图可能再次包含子视图。现在我应该在哪里创建子项?在视图控制器(最方便)还是在父视图(最近)中?

如果我使用ViewController,我有参考,我会很容易制作出口等,但是ViewController是否也应该做setTitle,setImage,background等东西?这绝对是最简单的解决方案。缺点是视图只是对象制作,这将导致视图控制器变得臃肿。

如果我使用视图,我将很难将插座返回到视图控制器,并且视图控制器最终几乎什么都不做。

苹果也没有太大帮助,官方的FoodTracker教程显示了ViewController和使用插座等的视图。

我现在的基本结构:

updateLayoutStates()
setupLayoutPositions()
updateLayoutPositions()
...
/// Setups the initial constraints for all views
func setupLayoutPositions() {
// add views by order of appearances
addSubview(languageBtn)
addSubview(playBtn)
addSubview(menuBtn)
//addSubview(barScrollOverlayView)
addSubview(barScrollView)
addSubview(collapseBtn)
// add bar scroll inner subviws by order of appearance
barScrollView.addSubview(barScrollContentView)
barScrollContentView.addSubview(speedContainerView)
barScrollContentView.addSubview(speedProgress)
barScrollContentView.addSubview(readingStratBtn)
// More code that adds constraints etc. etc.
...
/**
Updates all views based on the current status of the bar
*/
func updateLayoutStates() {
print("Bar updateLayoutStates")
// setup base layout
// setup permanent items, listed by appearance
languageBtn.backgroundColor = UIColorFromHex(Constants.Colors.dark_blue, alpha: 1)
languageBtn.setTitle("lang_da".localized, forState: .Normal)
languageBtn.postSetup()
languageBtn.setTitleColor(UIColorFromHex(Constants.Colors.white, alpha: 1), forState: .Normal)
playBtn.setImage(UIImage(named: "Play"), forState: .Normal)
playBtn.setImage(UIImage(named: "PlayActive"), forState: .Highlighted)
playBtn.setTitle("label_play_key".localized, forState: .Normal)
playBtn.postSetup()
...
/// updates the positions of all layouts based on the current status of the bar
func updateLayoutPositions() {
if currentBarState == BarState.EnabledStandardExpanded {
self.removeConstraint(collapseLeftConstraint)
self.addConstraint(collapseRightConstraint)
} else if currentBarState == BarState.EnabledStandardCollapsed {
self.removeConstraint(collapseRightConstraint)
self.addConstraint(collapseLeftConstraint)
}
}

非常感谢所有带有示例的解释,如果我不够清楚,我很乐意进一步解释。

一方面,你说的是好的建筑。另一方面,您需要有关特定视图结构的帮助。

1)对于第一部分,您有很多资源。DJohnsen已经提到了MVVM和VIPER,我认为这对Google来说是一个很好的搜索字符串。 我认为熟悉架构主题总是好的。每个架构都有权衡。 一个很好的起点是鲍勃叔叔的"清洁代码"。

  • Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin) https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

从那里发展出许多想法。

2)关于您的观点问题:

如果您有嵌套的视图层次结构,则考虑视图控制器包含可能是一个好主意。一旦您看到您的视图是由许多其他视图组成的,并且它变得更加复杂,您可能希望拆分组件。 你总是要考虑你试图解决的具体问题:

  • 是否只想显示一个标签和一个按钮?将它们直接添加到视图控制器并连接插座或设置目标/操作。

  • 您是否有一个带有标题、自定义子视图(也许还有表视图等)的复杂视图?使用子视图控制器

但要分解一下:

视图控制器和视图彼此非常接近。 在iOS中,我开始以以下方式处理视图和视图控制器:

  • 视图控制器应该是愚蠢的。它们的唯一用途是管理子控制器或设置几个视图的属性。视图控制器还管理高级屏幕处理(设备旋转、状态栏处理等)并与表示层通信。

  • 视图
  • 更愚蠢,应该只设置子视图、布局(设置布局约束)并提供一些自定义方法(可由视图控制器使用)。

这一切听起来有点困难:但我认为这对初学者来说是一个很好的指导方针。一段时间后,你会感到舒适。

你问的问题很好,但一段时间后你会自己回答。我认为最重要的是,您应该只将视图特定代码放入视图控制器和视图中。不多了。

其余的都很快升级为宗教战争:)

干杯奥
兰多

有很多方法/模式可以解决这个问题并避免视图控制器膨胀。 在看了 MVC、VIPER、MVVM 和许多其他内容之后,我喜欢 Clean Swift 的大部分实现。 它支持一次性函数、依赖注入,并保持视图控制器非常干净。

虽然起初它似乎有点矫枉过正(对于非常小的项目来说可能是),但我最近重构了一个越来越笨拙的OS X项目。 令人惊讶的是,现在实现新功能、隔离错误和重用代码是多么简单。 可能值得一试?

坏消息- 如果你问一千个开发人员对此的看法,你至少会得到一千个意见。

好消息- 该平台对他们来说足够灵活!

苹果在这里提供了MVC指南,https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html,我会给你我的看法:

通过一个非常基本的应用程序示例来选择和安排会议室:

模型如您所知,模型表示数据结构。 我为每个结构/类保留 1 个文件,并且我保留代码仅表示数据(而不是业务逻辑)。 我的会议室模型可能如下所示:

struct ConferenceRoom {
let maxOccupancy: Int
let roomNumber: Int
let hasProjector: Bool
var reservations: 
}

控制器我尝试将业务逻辑保留在控制器中(不要与视图控制器混淆)。 例如:

class ConferenceRoomController {
var conferenceRooms = [ConferenceRoom]()
init() {
...
}
func retrieveConferenceRoomsFromDatastore() -> [ConferenceRoom] {
...
}
func reserveConferenceRoom(roomNumber: Int, startDate: NSDate, endDate: NSDate) -> Bool {
...
}
func findRoomsForDateWithCapacity(capacity: Int, date: NSDate) -> [ConferenceRoom] {
...
}
}

View这通常是一个视图/视图控制器。 在IOS中,ViewcController既是视图,也是用于管理视图的控制器,这对许多人来说是一个困惑点,并且因为它基本上可以做任何事情,所以太多的业务逻辑或其他代码最终会出现在这里(膨胀)。 我尝试只在这里放置与显示数据相关的函数(而不是要显示的内容 - 即控制器)。 如果我以预期方式向视图添加子视图,我也会在这里这样做。

class ConferenceRoomScheduler: UIViewController {
@IBOutlet var numberOfParticipants: UITextField!
@IBOutlet var reservationDate: UITextField!
@IBOutlet var tableView: UITableView!
@IBOutlet var submitButton: UIButton!
let conferenceRoomController = ConferenceRoomController()
@IBAction func submitButtonPressed(sender: UIButton) {
let participants = Int(numberOfParticipants.text!)
if let participants = participants {
conferenceRoomController.findRoomsForDateWithCapacity(participants, date: NSDate())
} else {
print("Not a number")
}
}
}

这些类不完整,但希望能提供一些示例来说明要放在哪里的内容。 我发现这些类型的决策会随着您更习惯于为平台开发而发展。 我同意 - 一些模式,例如 Clean-Swift 似乎你会花很多时间"管道",如果你不熟悉具体的实现,你可能会。 例如,当我开始IOS开发时,我可以花几个小时把一个简单的tableView放在一起,它看起来很复杂。 现在,在完成太多次无法计数之后,功能齐全的 tableView 具有超出基础知识的功能,只需几分钟即可完成设置。 应用程序架构对我来说是一样的。 Clean-Swift(和其他)似乎不再太重了(好处超过了最初感知的复杂性)。

相关内容

最新更新