2

As I'm working through a test-driven development exercise to gain better understanding of how objects can be initialized and used I've run across a test case where I create an object such as a UITableView but I didn't have to use the init function of UITableView.

Here is a sample of the code:

import XCTest
@testable import PassionProject

class ItemListDataProviderTests: XCTestCase {

    var sut: ItemListDataProvider!
    var tableView: UITableView!

    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.

        sut = ItemListDataProvider()
        tableView = UITableView()
        sut.itemManager = ItemManager()
        tableView.dataSource = sut
    }

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

    func tests_numberOfSectionsIsTwo(){

        let numberOfSections = tableView.numberOfSections
        XCTAssertEqual(numberOfSections, 2)

    }

As I'm learning the swift language and OOP in general, I know initializers come in different flavors and I ASSUMED that in order to use an instance we will need to initialize it. However above I was able to create a UITableView instance and store it's memory inside a variable. I was even allowed to access it properties such as tableview.datasource.

I'd like to know am I correct in thinking that in order to use instance of any type of class, it must be initialized (if the stored properties aren't set by default)?

What did I just do in layman terms? Did I just allocate the memory?

Where I became confused is when reading Apple's documentation, this class has an initializer which I never had to use because I never set the frame or the style: init(frame: CGRect, style: UITableViewStyle)

Thanks in advance for commenting or answering.

Laurence Wingo
  • 3,912
  • 7
  • 33
  • 61

1 Answers1

7

The expression UITableView() invokes the initializer for UITableView. In more general terms, <someobject>() invokes the initializer for that object that does not take any parameters:

init() {
  //Initializer code goes here
}

You are correct that in order to use an object in Swift, you have to initalize it. Doing so both allocates the memory for the object and initializes it. Those two things can't be separated in Swift.

In Objective-C allocating and initializing objects are two distinct steps. You'll see the syntax SomeObject *object = [[SomeObject alloc] init] all over the place. That code invokes the SomeObject class's alloc method to allocate memory for the object, and then sends the newly allocated object an init method, which lets the object initialize it's variables and do other setup.

In Swift the system allocates the memory for you, and invoking an init method both allocates space for the object and initializes it.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thank you and that makes sense. Where I became confused is when reading Apple's documentation, this class has an initializer which I never had to use because I never set the frame or the style: init(frame: CGRect, style: UITableViewStyle) – Laurence Wingo Jan 12 '17 at 00:09
  • From my own understanding and looking at Apple's documentation, the init method for UITableView has two properties that aren't optional. So what I'm saying is that I never set those properties or called the init method but my test case was still able to use the object I believe. – Laurence Wingo Jan 12 '17 at 00:14
  • There is the concept of the *designated* initializer, which is the initializer that all other initializers for a class are supposed to call. I believe that for `UIView` subclasses like `UITableViewController`, you are supposed to call either `init(frame:style:)` or `init(coder:)` – Duncan C Jan 12 '17 at 00:16
  • 1
    You did call an init method. You called `init()`. You didn't call `init(frame:style:)` or `init(coder:)`, but you did call **an** initializer. – Duncan C Jan 12 '17 at 00:17
  • Weird...so I take it those properties (frame and style) were set to nil. You're saying I did call an initializer by instantiating it which called the designated initializer. Am I saying this correctly? If so, why doesn't the documentation read that those properties are optional? by placing a question mark behind them? – Laurence Wingo Jan 12 '17 at 00:22
  • 1
    You should be calling either `init(frame:style:)` or `init(coder:)`. See this link: http://stackoverflow.com/questions/7126726/ios-uiview-subclass-init-or-initwithframe (Writen for Objective-C but still relevant) – Duncan C Jan 12 '17 at 00:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132953/discussion-between-user6510422-and-duncan-c). – Laurence Wingo Jan 12 '17 at 00:27