Какова функция NSObject в StoryBoard / Interface Builder? - PullRequest
0 голосов
/ 27 августа 2018

В настоящее время я изучаю видеоурок о тестовой разработке iOS в Swift, но при тестировании Table View в View Controller я застреваю, так как не понимаю, зачем нам нужен NSObject в Interface Builder, как на картинке ниже :

Служба данных библиотеки фильмов наследуется классом NSObject:

enter image description here

класс MovieLibraryDataService выглядит так:

import UIKit

class MovieLibraryDataService: NSObject, UITableViewDataSource, UITableViewDelegate {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return UITableViewCell()
    }


}

и класс MovieLibraryDataService будет использоваться в XCTestCase следующим образом:

@testable import FilmFest
class LibraryViewControllerTests: XCTestCase {

    var sut: LibraryViewController!

    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
        sut = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LibraryViewControllerID") as! LibraryViewController
        _ = sut.view
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    // MARK: Nil Checks
    func testLibraryVC_TableViewShouldNotBeNil() {
        XCTAssertNotNil(sut.libraryTableView)
    }

    // MARK: Data Source
    func testDataSource_ViewDidLoad_SetsTableViewDataSource() {
        XCTAssertNotNil(sut.libraryTableView.dataSource)
        XCTAssertTrue(sut.libraryTableView.dataSource is MovieLibraryDataService)
    }

    // MARK: Delegate
    func testDelegate_ViewDidLoad_SetsTableViewDelegate() {
        XCTAssertNotNil(sut.libraryTableView.delegate)
        XCTAssertTrue(sut.libraryTableView.delegate is MovieLibraryDataService)
    }

    // MARK: Data Service Assumptions
    func testDataService_ViewDidLoad_SingleDataServiceObject() {
        XCTAssertEqual(sut.libraryTableView.dataSource as! MovieLibraryDataService, sut.libraryTableView.delegate as! MovieLibraryDataService)
    }



}

и определение LibraryViewController:

import UIKit

class LibraryViewController: UIViewController {

    @IBOutlet weak var libraryTableView: UITableView!
    @IBOutlet var dataService: MovieLibraryDataService!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.libraryTableView.dataSource = dataService
        self.libraryTableView.delegate = dataService
    }


}

Я действительно не понимаю, почему мне нужно сделать этот MovieLibraryDataService класс

Я обычно использую:

self.libraryTableView.dataSource = self
self.libraryTableView.delegate = self

но зачем мне писать:

self.libraryTableView.dataSource = dataService
self.libraryTableView.delegate = dataService

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

MovieLibraryDataService - это просто еще один класс, который реализует UITableViewDataSource и UITableViewDelegate, с той разницей, что раскадровка создает его и что экземпляр storyboard-created связан через IBOutlet @IBOutlet var dataService: MovieLibraryDataService!.Все объекты в раскадровке storyboard-created, поэтому необходимо привязать их к используемым переменным, если они не привязаны к другим переменным, которые вы уже используете.сказать, что он должен serve, в данном случае dataSource and delegate для tableView, поскольку он реализует эти протоколы делегатов.

Поскольку dataService создается в раскадровке, вы можете попробоватьесли вы можете связать dataService внутри раскадровки с tableView.Это возможно, потому что у вас есть dataService ссылка на раскадровку.Это заменит настройку dataSource and delegate в viewController.

Другой пример

AppDelegate также является NSObject внутри раскадровки, так что UIApplication/NSApplication внутри раскадровки можетссылка, которую следует использовать, позволяет избежать необходимости настраивать AppDelegate вне раскадровки.(В противном случае было бы некрасиво, может быть, это только macOS, поскольку приложения Mac должны показывать Menu, даже если оно пустое.)

0 голосов
/ 27 августа 2018

Редактировать

Вы можете использовать NSObject на Storyboard для различных целей, одним из которых может быть также делегирование. Вместо того, чтобы устанавливать это программно как:

self.libraryTableView.dataSource = self
self.libraryTableView.delegate = self

вы можете удерживать control и затем устанавливать соответствующих делегатов, как показано ниже:

enter image description here

Оригинальный ответ

Потому что MovieLibraryDataService соответствует UITableViewDataSource и UITableViewDelegate, а не вашему LibraryViewController.

Если вы хотите изменить его, как обычно, измените код на:

class LibraryViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var libraryTableView: UITableView!
    var dataService = MovieLibraryDataService()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.libraryTableView.dataSource = self
        self.libraryTableView.delegate = self
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return UITableViewCell()
    }
}

Лично я бы посоветовал оставить все как есть, поскольку Контроллеры представления имеют тенденцию расти и становиться такими, как мы его называем Контроллер массивного представления

...