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

标签 swift

我想实现我的自定义 MKAnnotation。我看了一下 MKAnnotation 协议(protocol)(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)
}

请注意坐标属性(这是一个只读的存储属性)。 以下是我如何实现此协议(protocol):

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
    }
}

但显然编译器提示我的 init 方法我试图分配给我的坐标属性 Cannot assign to 'coordinate' in 'self' 显然是因为它是只读属性。

以前在 Objective-C 中我们可以解决这个问题,因为属性由 ivars 支持。

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

我不知道如何在 Swift 中解决这个问题,或者我可能需要将其完全打开并将我的坐标更改为可读/可写?

最佳答案

您应该能够向它添加一个 setter 并将信息存储在一个内部坐标值中。因为你有一个 setter/getter ,它仍然符合协议(protocol):

var innerCoordinate: CLLocationCoordinate2D

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

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

这实际上是我实现只读和私有(private)属性的方式(使用协议(protocol)和工厂模式)。我使用公共(public)接口(interface)设置协议(protocol),使用私有(private)变量和 setter 设置类。它实际上是设置代码的 super 干净的方式(并且解决了 Swift 中缺少 protected /私有(private)属性的问题)。


这是我正在谈论的内容的抽象示例(如果您关心的话):

// this is your MKAnnotation in this example
protocol SomeProtocol {
    var getterProperty: String { get }
    var setterProperty: String { set get }

    func publicFunction(someStirng: String) -> ();

}

// setup a function that returns a class conforming to your needed protocol
func SomeClassMaker() -> SomeProtocol {
    // your internal class that no one can access unless by calling the maker function
    class SomeClassInternal: NSObject, SomeProtocol {

        // private and no one can get to me!
        var innerSetterProperty = "default setter";

        var getterProperty = "default getter"

        var setterProperty: String {
            get {
                return self.innerSetterProperty;
            }
            set {
                "hit"
                self.innerSetterProperty = newValue
            }
        }

        func publicFunction(someString: String) -> ()  {
            // anyone get me
            self.getterProperty = someString;
        }

        func privateFunction() -> () {
            // no one can get me except internal functions
        }

    }

    return SomeClassInternal();
}


// create the class
var classInstance = SomeClassMaker();

// totally fine!
classInstance.setterProperty = "secret string"
// prints "secret string"
classInstance.setterProperty;

// error! no public setter for "getter"
classInstance.getterProperty = "another secret"

classInstance.publicFunction("try secret again")
// prints "try secret again"
let blahed = classInstance.getterProperty

// error!
classInstance.privateFunction()

关于swift - 在 Swift 初始化期间设置只读存储属性的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24130616/

相关文章:

Swift - 在整个结构中搜索字符串

Swift:初始化器中的 self 具有类型 (T) -> () -> T

iOS, subview 大小无故改变

来自可选 Double 的 Swift 字符串

iOS Core Data NSFetchedResultController.fetchedObject 返回错误数据和 (0,0) 注解

swift - Vapor 2,一对多关系

ios - Swift 3 - Android 相当于使用日历类过去 12 个月

swift - 菜单栏弹出窗口在 Dock 图标上打开,单击 OSX

ios - Swift 3 中的不安全字节

swift - 如何快速删除 UIMenuController 项?