Как вернуть nil в swift в пользовательский инициализатор?

Я пытаюсь написать пользовательский инициализатор в swift. У меня есть что-то вроде этого:

convenience init(datasource:SomeProtocol) {
    assert(datasource != nil, "Invalid datasource")
    if(datasource == nil) {
        return nil
    }
    self.init()
}

Линия "return nil" дает мне эту ошибку: "не удалось найти перегрузку для" __conversion ", которая принимает предоставленные аргументы"

Итак, все, что я пытаюсь сделать, это заставить этот инициализатор удобства возвращать нуль, если вызывающий объект не предоставляет действительный источник данных.

Что я здесь делаю неправильно?

Спасибо

Ответ 1

Это потому, что initializers фактически не имеет никакого значения. Вы не можете вернуть nil, если метод не ожидает типа возврата.

Чтобы добиться того, что вы пытаетесь сделать (например, заставить ваш класс иметь источник данных), просто добавьте свой источник данных не. Переменные, которые не являются необязательными должны иметь значение (поэтому не могут быть nil) и должны быть инициализированы.

Ответ 2

Обновление: Начиная с Xcode 6.1 beta 1 (доступно в Центре Mac Dev), инициализаторы Swift могут быть объявлены для возврата необязательного

convenience init?(datasource:SomeProtocol) {
    if datasource == nil {
        return nil
    }
    self.init()
}

или неявно-развернутый необязательный:

convenience init!(datasource:SomeProtocol) {
    if datasource == nil {
        return nil
    }
    self.init()
}

Ответ 3

Я думаю, что это сработает, хотя это не ясно из вашего поста, где вы работаете с dataSource:

class func instOrNil(datasource:A) -> Self? {
    // do something with datasource
    if datasource.isValid() {
        return self()
    } else {
        return nil
    }
}

Обновить Swift 3

Теперь вы можете вернуть nil из init?(...):

init?(datasource: A){
    if datasource.isValid() {
        // initialise your properties from datasource
    } else {
        return nil
    }
}

Ответ 4

Если суперкласс этого класса является классом Objective-C, и вы знаете, что есть какой-то ввод, который заставит его инициализатор возвращать nil, вы можете просто передать этот вход в инициализатор суперкласса, и это вызовет ваш инициализатор для возврата nil:

import Foundation
class Foo : NSURL {
  convenience init(x: Int) {
    if x == 42 {
      self.init(string: "http://www.google.com/")
    } else {
      self.init(string: "not a url") // returns nil
    }
  }
}

let a: Foo? = Foo(x: 42)
println(a) // prints "Optional(http://www.google.com/)"
let b: Foo? = Foo(x: 17)
println(b) // prints "nil"

Конечно, это работает только в том случае, если вам посчастливилось иметь суперкласс, инициализатор которого вернет нуль. Таким образом, это не общее решение.