2016-05-31 54 views
0

所以我是新的iOS但經驗豐富的Android和我開始獲得大多數東西的主旨,但我很難理解什麼去哪裏,爲什麼它是這樣的...Swift的iOS代碼結構,所有代碼在哪裏?

當你只使用故事板很容易實現MVC模式(或任何其他視圖分離模式),但是當您將代碼中的所有內容製作出來時,我感覺它會變得雜亂無章。

比方說,我有一個ViewController與父視圖包含子視圖,其中可能包含子視圖。現在我應該在哪裏創建孩子?在ViewController(最方便)還是在父視圖(最近)?

如果我使用的ViewController我有參考,我會有一個容易的時間做網點等,但應該ViewController然後也做像setTitle,setImage,背景等東西?這絕對是最簡單的解決方案。缺點是Views僅僅是造成ViewController變得臃腫的對象。

如果我使用視圖,我很難將視點返回給ViewController,而ViewController最終將不會做任何事情。

蘋果是沒有太大的幫助,這時三OFFICIEL FoodTracker教程同時顯示視圖控制器,並使用插座等等,等等瀏覽

基本結構,我現在:

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

一方面你說的是好的建築。另一方面,你需要一些關於你的具體視圖結構的幫助。

1)對於第一部分,您有很多資源。 DJohnsen已經提到了MVVM和VIPER,我認爲這對Google來說是一個很好的搜索字符串。 我認爲總是適合建築主題。每個架構都有所折衷。 一個好的起點是叔叔Bobs「乾淨的代碼」。

從那裏很多想法演變。

2)關於你的觀點的問題:

如果你有一個嵌套的視圖層次它可能是一個好主意,想視圖控制器遏制的。只要你看到,你的視圖是由許多其他視圖組成的,它變得更加複雜,你可能需要拆分組件。 你總是要想想你正在試圖解決的具體問題:

  • 你只想顯示一個標籤和一個按鈕?將它們直接添加到視圖控制器並連接插座或設置目標/操作。

  • 你有頭,自定義子視圖一個複雜的視圖,也許還的tableView等?使用子視圖控制器

但打破它:

視圖控制器和視圖都非常接近對方。 在iOS中,我開始處理意見和看法控制器以下列方式:

  • 視圖控制器應該是愚蠢的。他們唯一的目的是管理子控制器或設置一些視圖的屬性。視圖控制器還管理高級屏幕處理(設備旋轉,狀態欄處理等)並與表示層進行交談。

  • 視圖更愚蠢,應該只設置子視圖,佈局(設置佈局約束)並提供一些自定義方法(視圖控制器可以使用)。

這一切聽起來有點難:但我認爲這是一個很好的指導初學者。過一段時間後,你會感到舒適。

你問的問題很好,但你會在一段時間後自己回答。我認爲最重要的是你應該只將視圖特定的代碼放入視圖控制器和視圖中。不多。

所有剩下的迅速升級爲宗教戰爭:)

乾杯
奧蘭多

+0

謝謝,我開始了來更好地理解一切。此外,我已經意識到這沒有人回答:)。從Android的角度來看,我猜ViewController與Fragment類似。在Android中,只要您在代碼中執行UI,而不是在xml中,就可以隨心所欲地搞定所有內容。 – Warpzit

+0

是的。可以說,ViewController就像Android中的Activity或Fragment。我希望你能理解「視圖控制器遏制」的含義。如果沒有:https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html – orschaef

+0

是的,這已經是我決定去的方法。我已經開始了一個簡單的視圖,這個視圖變得越來越複雜,在這一點上我意識到它是一個子視圖控制器:)但正如你所說的,我們仍然可以這樣編碼,這不是一個好方法。 – Warpzit

1

有很多方法/模式來解決這個問題,並避免視圖控制器膨脹。在看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: 
} 

控制器 我儘量保持業務邏輯控制器(不要與ViewControllers混淆)。例如:

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] { 
    ... 
    } 
} 

查看 這通常是一個視圖/視圖控制器。在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(以及其他)似乎不再太重(並且好處超出了初始感知的複雜度)。

+0

是這一切聽起來不錯,但分離 - 一切投入使用情況下,我會花很多時間做豐滿。這似乎更像MVVM模式的工作。但是我的問題實際上比這更簡單。我的問題是什麼時候我把功能代碼放在視圖中,什麼時候放在ViewController中,是否有任何指導或不存在?上面提供的代碼在視圖中開始,並且已經被移至ViewController。兩種方式都可以工作,但首選的是? – Warpzit

+0

@DJohnson:我對clean-swift.com上的概念有一個問題。作者用VC - > I - > P - > VC設置循環依賴關係。我認爲從視圖控制器到交互器的直接依賴關係並不好。這意味着視圖控制器知道業務邏輯接口。從我的角度來看,風險投資者只應該通知用戶觸發了任何事件,並從表示層獲得任何結果...但我不想在這裏開始火焰戰爭;) – orschaef