在开关中调用属性设置器而不是获取器(Xcode 9.3 和 9.4)

Posted

技术标签:

【中文标题】在开关中调用属性设置器而不是获取器(Xcode 9.3 和 9.4)【英文标题】:Property setter called instead of getter in switch (Xcode 9.3 & 9.4) 【发布时间】:2018-06-06 17:20:02 【问题描述】:

考虑以下对象:

enum SetType: String 
    case anaerobic, isometric


class RealmSet: Object 
   @objc dynamic private var setType: String = ""
    var type: SetType 
        get 
            guard let unwrappedSetType = SetType(rawValue: setType) else 
                return .anaerobic
            
            return unwrappedSetType
        
        set 
            self.setType = newValue.rawValue
        
    


protocol ExerciseSet 
    var setType: SetType  get 


class Exercise: Object 
   private let setsValues = List<RealmSet>()
   var sets: [ExerciseSet] 
        var sets = [ExerciseSet]()
        for setValue in self.setsValues 
            switch setValue.type 
            case .anaerobic:
                // Do Something

            case .isometric:
                // Do Something
            
        

        return sets
    

发生的情况是,当我尝试迭代 setsValues 的数组并执行 switch 以发现 RealmSet 的类型,而不是调用来自 RealmSettype getter 属性时,而是调用 setter。由于这个对象是一个 Realm 对象,应用程序会立即崩溃,因为我没有运行写事务,这是真的,因为我只需要访问属性 getter,而不是它的 setter。

这种情况最奇怪的是当 Xcode 版本低于 9.3 时不会发生这种情况。这只发生在 Xcode 9.3 和 9.4 中。当我使用 Xcode 9.2 时,一切正常。

我不知道问题出在哪里。如果是 Realm lib,Xcode 版本 9.3 和 9.4 或什么的一些变化。

【问题讨论】:

您确定不是 switch 语句的主体导致崩溃吗?您是否尝试仅在两个 case 语句中打印某些内容,以确保您不会意外修改那里的任何内容? @DávidPásztor 是的。我还在RealmSet type 属性的gettersetter 内设置了一个断点,当执行切换时,它到达设置器断点。我也为 XCode 9.2 做了这个,但是在这个版本中,getter 被调用了。 我试图重现您的问题,但是当 Exercise.setsValues 是私有的时,您应该如何向它添加值? sets 是一个访问 setsValues 的计算属性,所以我似乎无法找到一种方法来为其中任何一个添加值从而触发错误。 @DávidPásztor setsValues 是私有属性,因为您不应该在模型之外更改其值。这就是我创建这个计算属性sets 的原因,因为它管理对这个 List 属性的访问和修改。由于两者(setsValuessets)属于同一类,我看不出有任何原因导致您因私人保护而无法访问。 我的意思是,如果您没有展示如何从 setsValues 内部修改 setsValues,则很难重现您的问题。您应该修改问题中的代码以包含minimal reproducible example。 【参考方案1】:

不确定到底哪里出了问题¹,但在同一个类中有一个读/写 var type 和一个单独的属性 setType 对我来说真的很可疑。尝试将setType 重命名为rawSetType 之类的名称,以至少确保它不会与type 属性发生冲突。

¹ 必须与 Realm.Object 是一个 Objective-C 类相关,这意味着对于 type 属性将有一个名为 setType 的设置器。

【讨论】:

我已重命名所有这些 var 以确保这不是名称冲突,并且与 var 名称无关。【参考方案2】:

对于那些面临同样问题的人,在处理 Realm 时不要使用get set。 Realm 通过 KVO 访问属性,因此在某些情况下它会丢失并导致这种错误。使用get-only 属性结合函数来设置此属性,而不是使用get set

【讨论】:

以上是关于在开关中调用属性设置器而不是获取器(Xcode 9.3 和 9.4)的主要内容,如果未能解决你的问题,请参考以下文章

将 JQuery 动画附加到方法/设置器而不是 CSS 属性?

Laravel 获取构建器而不是关系

python 使用此包装器而不是崩溃从函数中获取默认输出。

通用选择器而不是逗号分隔的元素

在 Instruments 中运行的 iPhone 应用程序因无法识别的选择器而失败

如何在旧视图上显示微调器而不是主干中的空白页面