在Swift中初始化期间设置只读存储属性的值

在Swift中初始化期间设置只读存储属性的值,swift,Swift,我想实现我的自定义注释。我看了一下MKAnnotation协议(MKAnnotation.h)。 具体如下: // // MKAnnotation.h // MapKit // // Copyright (c) 2009-2014, Apple Inc. All rights reserved. // protocol MKAnnotation : NSObjectProtocol { // Center latitude and longitude of the annota

我想实现我的自定义注释。我看了一下MKAnnotation协议(MKAnnotation.h)。 具体如下:

//
//  MKAnnotation.h
//  MapKit
//
//  Copyright (c) 2009-2014, Apple Inc. All rights reserved.
//

protocol MKAnnotation : NSObjectProtocol {

    // Center latitude and longitude of the annotation view.
    // The implementation of this property must be KVO compliant.
    var coordinate: CLLocationCoordinate2D { get }

    // Title and subtitle for use by selection UI.
    @optional var title: String! { get }
    @optional var subtitle: String! { get }

    // Called as a result of dragging an annotation view.
    @optional func setCoordinate(newCoordinate: CLLocationCoordinate2D)
}
请注意坐标属性(它是只读存储属性)。 下面是我如何实现这个协议的:

class RWDefaultPin: NSObject, MKAnnotation {
    var title:String = ""
    var subtitle:String = ""
    var groupTag:String = ""
    var coordinate: CLLocationCoordinate2D { get {
        return self.coordinate // this is obviously wrong because property's trying to return itself
    } };


    init(coordinate:CLLocationCoordinate2D) {
        super.init()
        self.coordinate = coordinate
    }
}
var innerCoordinate: CLLocationCoordinate2D

var coordinate: CLLocationCoordinate2D { 
    get {
        return self.innerCoordinate
    } 
    set {
        self.innerCoordinate = newValue
    }
};

init(coordinate:CLLocationCoordinate2D) {
    super.init()
    self.innerCoordinate = coordinate
}
但显然,编译器对我试图分配给坐标属性的
init
方法表示不满,因为它是只读属性,所以
无法分配给'self'
中的'coordinate'

在之前的Objective-C中,我们可以克服这个问题,因为房地产由IVAR支持

我希望Swift中有一个访问修饰符,这样我就可以在类中定义一个私有属性,并在init上设置它的值,在坐标的get操作上返回它的值,但是没有这样的事情


我不知道如何在Swift中解决此问题,或者我需要将其完全打开并更改坐标以使其可读/写

您应该能够向其添加一个
设置器
,并将信息存储在内部坐标值中。因为您有一个getter,所以它仍然符合协议:

class RWDefaultPin: NSObject, MKAnnotation {
    var title:String = ""
    var subtitle:String = ""
    var groupTag:String = ""
    var coordinate: CLLocationCoordinate2D { get {
        return self.coordinate // this is obviously wrong because property's trying to return itself
    } };


    init(coordinate:CLLocationCoordinate2D) {
        super.init()
        self.coordinate = coordinate
    }
}
var innerCoordinate: CLLocationCoordinate2D

var coordinate: CLLocationCoordinate2D { 
    get {
        return self.innerCoordinate
    } 
    set {
        self.innerCoordinate = newValue
    }
};

init(coordinate:CLLocationCoordinate2D) {
    super.init()
    self.innerCoordinate = coordinate
}
这实际上就是我实现只读和私有属性(使用协议和工厂模式)的方式。我使用公共接口设置协议,使用私有变量和setter设置类。它实际上是一种超级干净的代码设置方式(并且可以避免Swift中缺少受保护/私有属性)


下面是我所说内容的一个抽象示例(如果您愿意):


即使协议中的属性是
{get}
,这只是建立了一个最低标准。完全可以将其定义为读写:

class MyAnnotation:NSObject, MKAnnotation
{
    var coordinate:CLLocationCoordinate2D

    init(coordinate:CLLocationCoordinate2D) {
        self.coordinate = coordinate
    }
}
或者,如果您确实希望将其保持为只读,可以使用let:

class MyAnnotation:NSObject, MKAnnotation
{
    let coordinate:CLLocationCoordinate2D

    init(coordinate:CLLocationCoordinate2D) {
        self.coordinate = coordinate
    }
}

您是否尝试创建真正私有的
坐标
属性?一个可以在初始化期间设置的属性,它是公共
坐标
getter返回的值?为什么不向它添加一个
集合
?@Firo,这个属性在Objective-C中是只读的,如果您注意到,apple在MKAnnotation.h中将其定义为只读(变量坐标:CLLocationCoordinate2D{get})@CjCoax并不意味着你的类可以给它一个setter。这只意味着协议不会强制设置器,它会阻止任何不知道实际类的人设置属性。@CjCoax,我犯了一个错误。显然你不能做我建议的事。在setter中设置属性实际上会运行到一个无限循环中(因为现在设置了属性,所以它会再次调用setter)。很抱歉请参见“编辑”。@JamieForrest如果您有权访问该类,则会这样做,但如果您通过协议访问设计代码,则访问器类只能获得它。这是拥有私有变量和函数的好方法。它还允许进行一些清洁单元测试。让我用一个彻底的例子来完善我的答案。。。给我一个sec@JamieForrest,我用一个简短的例子编辑了答案。我在最初的回答中也犯了一个错误。