Редизайн Init (MKAnnotation)

class Point: NSObject, MKAnnotation {
var id: String?
var title: String?
var coordinate: CLLocationCoordinate2D
var subtitle: String?



init(id: String, dictionary: Dictionary<String, AnyObject>){
    self.id = id

    if let title = dictionary["title"] as? String {
        self.title = title
    }

    if let subtitle = dictionary["subtitle"] as? String {
        self.subtitle = subtitle
    }

    if let coords = dictionary["coordinates"] as? [String:[String:Double]] {
        self.coordinate.latitude = coords.values.first!["latitude"]!
        self.coordinate.longitude = coords.values.first!["longitude"]!
    }
   super.init()
}
/*
init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D){
    self.title = title
    self.subtitle = subtitle
    self.coordinate = coordinate

}*/

}

Реализован инициализатор для создания точки На карте. I must redesign init because I use Firebase and results from database are in dictionary.
Он пишет: свойство self.координата, не инициализированная в неявно сгенерированном super.init call

1 ответ

  1. init(id: String, dictionary: Dictionary<String, AnyObject>){
        self.id = id
    
        if let title = dictionary["title"] as? String {
            self.title = title
        }
    
        if let subtitle = dictionary["subtitle"] as? String {
            self.subtitle = subtitle
        }
    
        if let coords = dictionary["coordinates"] as? [String:[String:Double]] {
            self.coordinate.latitude = coords.values.first!["latitude"]!
            self.coordinate.longitude = coords.values.first!["longitude"]!
        }
        super.init()
    }
    

    Таким образом, проблема здесь в основном заключается в том, что вы только когда-либо инициализировать свое coordinateсвойство в an if. Поскольку coordinateне помечен как необязательный , ему будет дано значение перед вызовомsuper.init(), согласно правилам SWIFT инициализаторов.

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

    Проверка безопасности 1

    Назначенный инициализатор должен гарантировать, что все свойства
    введенные его классом инициализируются перед делегированием до a
    инициализатор суперкласса.

    Вы можете сделать coordinateнеобязательную переменную экземпляра, как и другие переменные экземпляра. Тем не менее, я бы сказал, что, вероятно, имеет смысл, чтоid&title, вероятно, также не являются необязательными, и все эти свойства, вероятно, должны быть letпостоянными.

    Как таковой, я бы переписал ваш класс и этот инициализатор как таковой:

    class Point: NSObject, MKAnnotation {
    
        let id: String
        let title: String?
        let coordinate: CLLocationCoordinate2D
        let subtitle: String?
    
        init?(id: String, dictionary: [String: AnyObject]){
            self.id = id
    
            title = dictionary["title"] as? String
    
            subtitle = dictionary["subtitle"] as? String
    
            guard let 
                coordinates = dictionary["coordinates"] as? [String: [String: Double]], 
                latitude = coordinates.values.first?["latitude"],
                longitude = coordinates.values.first?["longitude"] else {
    
                    return nil
            }
    
            coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    
           super.init()
        }
    }
    

    Теперь у вас есть отказоустойчивый инициализатор . Если какое-либо из значений в словаре неверно, инициализатор возвращает nil. В противном случае все значения будут правильно инициализированы.