<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                裝飾者模式可以動態的給指定的類添加一些行為和職責,而不用對原代碼進行任何修改。當你需要使用子類的時候,不妨考慮一下裝飾者模式,可以在原始類上面封裝一層。 在 Swift 里,有兩種方式實現裝飾者模式:擴展 (Extension) 和委托 (Delegation)。 ### 擴展 擴展是一種十分強大的機制,可以讓你在不用繼承的情況下,給已存在的類、結構體或者枚舉類添加一些新的功能。最重要的一點是,你可以在你沒有訪問權限的情況下擴展已有類。這意味著你甚至可以擴展 Cocoa 的類,比如?`UIView`?或者?`UIImage`?。 舉個例子,在編譯時新加的方法可以像擴展類的正常方法一樣執行。這和裝飾器模式有點不同,因為擴展不會持有擴展類的對象。 ### 如何使用擴展 想象一下這個場景,我們需要在下面這個列表里展示數據: [![](http://cdn2.raywenderlich.com/wp-content/uploads/2014/11/swiftDesignPattern3-480x262.png)](http://cdn2.raywenderlich.com/wp-content/uploads/2014/11/swiftDesignPattern3-480x262.png) 專輯標題從哪里來??`Album`?本身是個?`Model`?對象,所以它不應該負責如何展示數據。你需要一些額外的代碼添加展示數據的邏輯,但是為了保持?`Model`?的干凈,我們不應該直接修改代碼,因為這樣不符合單一職責原則。?`Model`?層最好就是負責純粹的數據結構,如果有數據的操作可以放到擴展中完成。 接下來我們會創建一個擴展,擴展現有的?`Album`?類,在擴展里定義了新的方法,返回更適合`UITableView`?展示用的數據結構。 數據的結構大概是這樣: [![](http://cdn5.raywenderlich.com/wp-content/uploads/2013/08/delegate2-480x67.png)](http://cdn5.raywenderlich.com/wp-content/uploads/2013/08/delegate2-480x67.png) 新建一個 Swift 文件:`AlbumExtensions`?,在里面添加如下擴展: ~~~ extension Album { func ae_tableRepresentation() -> (titles:[String], values:[String]) { return (["Artist", "Album", "Genre", "Year"], [artist, title, genre, year]) } } ~~~ 在方法的前面有個?`ae_`?前綴,是?`AlbumExtension`?的縮寫,這樣有利于和類的原有方法進行區分,避免使用的時候產生沖突。現在很多還在維護中的第三方庫都已經改成了這個風格。 注意:類是可以重寫父類方法的,但是在擴展里不可以。擴展里的方法和屬性不能和原始類里的方法和屬性沖突。 思考一下這個設計模式的強大之處: * 我們可以直接在擴展里使用?`Album`?里的屬性。 * 我們給?`Album`?類添加了內容但是并沒有繼承它,事實上,使用繼承來擴展業務也可以實現一樣的功能。 * 這個簡單的擴展讓我們可以更好地把?`Album`?的數據展示在?`UITableView`?里,而且不用修改源碼。 ### 委托 裝飾者模式的另一種實現方案是委托。在這種機制下,一個對象可以和另一個對象相關聯。比如你在用?`UITableView`?,你必須實現?`tableView(_:numberOfRowsInSection:)`?這個委托方法。 你不應該指望?`UITableView`?知道你有多少數據,這是個應用層該解決的問題。所以,數據相關的計算應該通過?`UITableView`?的委托來解決。這樣可以讓?`UITableView`?和數據層分別獨立。視圖層就負責顯示數據,你遞過來什么我就顯示什么。 下面這張圖很好的解釋了?`UITableView`?的工作過程: [![](http://cdn5.raywenderlich.com/wp-content/uploads/2013/08/delegate-480x252.png)](http://cdn5.raywenderlich.com/wp-content/uploads/2013/08/delegate-480x252.png) `UITableView`?的工作僅僅是展示數據,但是最終它需要知道自己要展示那些數據,這時就可以向它的委托詢問。在 objc 的委托模式里,一個類可以通過協議來聲明可選或者必須的方法。 看起來似乎繼承然后重寫必須的方法來的更簡單一點。但是考慮一下這個問題:繼承的結果必定是一個獨立的類,如果你想讓某個對象成為多個對象的委托,那么子類這招就行不通了。 注意:委托模式十分重要,蘋果在 UIKit 中大量使用了該模式,基本上隨處可見。 ### 如何使用委托模式 打開?`ViewController.swift`?文件,添加如下私有變量: ~~~ private var allAlbums = [Album]() private var currentAlbumData : (titles:[String], values:[String])? private var currentAlbumIndex = 0 ~~~ 在?`viewDidLoad`?里面加入如下內容: ~~~ override func viewDidLoad() { super.viewDidLoad() //1 self.navigationController?.navigationBar.translucent = false currentAlbumIndex = 0 //2 allAlbums = LibraryAPI.sharedInstance.getAlbums() // 3 // the uitableview that presents the album data dataTable.delegate = self dataTable.dataSource = self dataTable.backgroundView = nil view.addSubview(dataTable!) } ~~~ 對上面三個部分進行拆解: 1. 關閉導航欄的透明效果 2. 通過 API 獲取所有的專輯數據,記住,我們使用外觀模式之后,應該從?`LibraryAPI`?獲取數據,而不是?`PersistencyManager`?。 3. 你可以在這里設置你的?`UITablweView`?,在這里聲明了?`UITableView`?的?`delegate`?是當前的?`ViewController`?。事實上你用了 XIB 或者 StoryBoard ,可以直接在可視化的頁面里拖拽完成。 接下來添加一個新的方法用來更方便的獲取數據: ~~~ func showDataForAlbum(albumIndex: Int) { // defensive code: make sure the requested index is lower than the amount of albums if (albumIndex < allAlbums.count && albumIndex > -1) { //fetch the album let album = allAlbums[albumIndex] // save the albums data to present it later in the tableview currentAlbumData = album.ae_tableRepresentation() } else { currentAlbumData = nil } // we have the data we need, let's refresh our tableview dataTable!.reloadData() } ~~~ `showDataForAlbum()`?這個方法獲取最新的專輯數據,當你想要展示新數據的時候,你需要調用`reloadData()`?這個方法,這樣?`UITableView`?就會向委托請求數據,比如有多少個?`section`有多少個?`row`?之類的。 在?`viewDidLoad`?里面調用上面的方法: ~~~ self.showDataForAlbum(currentAlbumIndex) ~~~ 這樣應用一啟動就會去加載當前的專輯數據。因為?`currentAlbumIndex`?的默認值是 0 ,所以一開始會默認顯示第一章專輯的信息。 接下來我們該去完善?`DataSource`?的協議方法了。你可以直接把委托方法寫在類里面,當然如果你想讓你的代碼看起來更整潔一點,則可以放在擴展里。 在文件底部添加如下方法,注意一定要放在類定義的大括號外面,因為這兩個家伙不是類定義的一部分,它們是擴展: ~~~ extension ViewController: UITableViewDataSource { } extension ViewController: UITableViewDelegate { } ~~~ 上面就是實現委托的方法 - 你可以把協議想象成是與委托之間的約定,只要你實現了約定的方法,就算是實現了委托。在我們的代碼中,?`ViewController`?需要遵守?`UITableViewDataSource`和?`UITableViewDelegate`?的協議。這樣?`UITableView`?才能確保必要的委托方法都已經實現了。 在?`UITableViewDataSource`?對應的那個擴展里加上如下方法: ~~~ func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if let albumData = currentAlbumData { return albumData.titles.count } else { return 0 } } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell if let albumData = currentAlbumData { cell.textLabel?.text = albumData.titles[indexPath.row] if let detailTextLabel = cell.detailTextLabel { detailTextLabel.text = albumData.values[indexPath.row] } } return cell } ~~~ `tableView(_:numberOfRowsInSection:)`?返回需要展示的行數,和存儲的數據中的 title 的數目相同。 `tableView(_:cellForRowAtIndexPath:)`?創建并且返回了一個單元格,上面有標題和對應的值。 注意:你可以把這些方法直接加在類聲明里面,也可以放在擴展里,編譯器不會去管數據源到底在哪里,只要能找到對應的方法就可以了。而我們之所以這樣做,是為了方便其他人閱讀。 此時再構建項目,你可以看到如下內容: [![](http://cdn3.raywenderlich.com/wp-content/uploads/2014/11/Screen-Shot-2014-11-11-at-12.38.53-AM-179x320.png)](http://cdn3.raywenderlich.com/wp-content/uploads/2014/11/Screen-Shot-2014-11-11-at-12.38.53-AM-179x320.png) 是的,顯示成功啦!目前的項目源碼在這里:[BlueLibrarySwift-Part1](http://cdn5.raywenderlich.com/wp-content/uploads/2014/11/BlueLibrarySwift-Part1.zip),如果遇到什么問題你可以下載下來對比一下。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看