在提供代码示例的教程和示例中,有时我看到Xcode的Project导航器中的项目文件按照MVC模式按组排列(" Views"," Controllers& #34;,"模型"),以及其他时间按功能组织成组("登录","清单",例如)。
关于iOS,是否有任何Apple的会议/推荐? 哪个应该是最好的做法?
答案 0 :(得分:16)
开发人员以多种方式组织他们的组,代码和文件。但我使用如下内容:
CoreData :包含DataModel和实体类。
扩展程序:包含一个类(默认的apple类扩展+项目类扩展。)
Helper :包含第三方类/框架(例如SWRevealController)+桥接类(例如基于Swift的项目中的Obj C类)
模型:创建一个单例类(例如,AppModel - NSArray,NSDictionary,String等)来保存数据。解决和存储数据的Web服务响应也在这里完成。
服务:包含Web服务流程(例如,登录验证,HTTP请求/响应)
查看:包含Storyboard,LaunchScreen.XIB和View Classes。创建子文件夹单元格 - 包含UITableViewCell,UICollectionViewCell等。
控制器:包含与UIElements相关的逻辑或代码(例如,UIButton的参考+点击动作)
此结构来自another Stack Overflow post。
这些也可能对您有所帮助:
答案 1 :(得分:6)
我实际上创建了一个项目来演示我认为我的小型或中型代码库的Xcode项目结构。你可以找到它here。
以下是它的概述:
答案 2 :(得分:0)
这些天:制作更大的文件
我不愿意再使用“模型”文件夹或“控制器”文件夹在MVC级别分离逻辑。
从Objective-C到Swift过渡期间,对我来说最大的转变就是可以使用命名空间。而且,Swift中的访问控制要好得多。
一旦您的代码成为“内部”或“公开”代码,它就会保留更集中的文件。
因此,我一直试图将具有共同目的的逻辑分组在一起。事实证明这很棘手,但是下面是一个示例,说明如何使用访问控制使项目的其余部分不知道“ ReportTableViewCell”,该子类仅在我的应用程序的特定场景中使用。
以下内容位于单个文件中,唯一不是私有的是视图控制器。
final class ReportsViewController: UIViewController {
private let tableView = ReportTableView()
private let controller = try! ReportFetchController<ReportTableView>(context: CoreDataManager.sharedInstance.viewContext)
private lazy var tableViewHandler = ReportsTableViewHandler(controller)
... etc ...
}
private final class ReportTableViewCell: UITableViewCell {
...etc...
}
private final class ReportTableView: UITableView {
func dequeue(at indexPath: IndexPath, for record: Report) -> ReportTableViewCell {
...etc...
}
override init(frame: CGRect, style: UITableView.Style) {
// register cell here
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
private final class ReportsTableViewHandler: NSObject, UITableViewDataSource, UITableViewDelegate {
private let controller: ReportFetchController<ReportTableView>
init(_ controller: ReportFetchController<ReportTableView>) {
self.controller = controller
}
func numberOfSections(in tableView: UITableView) -> Int {
return controller.fetchedResultsController.sections?.count ?? 0
}
...etc...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let tableView = tableView as! ReportTableView
let entity = controller.fetchedResultsController.object(at: indexPath) as Report
return tableView.dequeue(at: indexPath, for: entity)
}
...etc...
}
// This is a subclassed NSFetchedResultsController
private final class ReportFetchController<D: FetchedResultsControllerDelegate>: FetchedResultsController<D> where D.Record: Report {
...etc...
override func predicate() -> NSCompoundPredicate {
var predicates = [NSPredicate]()
if let property = property {
predicates.append(NSPredicate(format: "property == %@", property))
}
return NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
}
private let sectionKeyPath = "created"
override func sectionNameKeyPath() -> String {
return sectionKeyPath
}
override func sortDescriptors() -> [NSSortDescriptor] {
return [NSSortDescriptor(key: sectionKeyPath, ascending: false)]
}
}
我也避免使用名为“ helpers”或“ extensions”的文件夹,因为该文件夹非常开放。这是我们作为程序员所做的。我们编写“帮助”代码,并出于目的扩展代码。
例如,在决定将哪个视图控制器压入堆栈时,需要以下内容。因此,我在需要它的文件中私下扩展了它。
private extension Boundary {
var requiresDirection: Bool {
switch self {
case .ceiling: return false
case .wall: return true
case .fence: return true
}
}
}
'requiresDirection'属性对我项目中的其他任何内容(包括'Boundary'枚举)都没有用。因此,让我们将其本地化到程序中需要它的部分,隐藏在文件的深处。