【问题标题】:Protocol reference in swift is throwing segmentation fault 11swift 中的协议参考引发分段错误 11
【发布时间】:2015-02-07 18:10:01
【问题描述】:

我正在尝试在 Swift 中创建一个 Date 和 Calendar 实现,大量使用协议,但它开始在每种方法中抛出分段错误 11。我现在是这样的:

protocol CalendarUnit {
  typealias C: Calendar
  init(_ date: Date<C>)
}

protocol Calendar {
  typealias Second: CalendarUnit
}

struct GregorianCalendar: Calendar {

  struct Second: CalendarUnit {
  }
}

struct Date<C: Calendar> {
  let timestamp: Int

  var second: C.Second { return C.Second(self) }
}

怀疑是因为两个协议的递归但不确定如何以另一种方式实现这一部分。任何帮助表示赞赏,在此先感谢

编辑

还可以在 calendarunit 的初始化器和它所属的日历之间使用类型限制。

protocol CalendarUnit {
  init<C>(date: Date<C>)
}

protocol Calendar {

  typealias Year: CalendarUnit
}

struct GregorianCalendar: Calendar {

  struct Year: CalendarUnit {

    init<C>(date: Date<C>) {
    }
  }
}

struct JulianCalendar: Calendar {

  struct Year: CalendarUnit {

    init<GregorianCalendar>(date: Date<GregorianCalendar>) {
    }
  }
}

struct Date<C: Calendar> {
}

在示例中,我可以插入任何日历(公历中的朱利安)并且将满足协议需求,但它不能保证它是相同的日历。有没有办法强制执行此限制,最好不必在 typealias 中重复日历的名称?。

【问题讨论】:

  • 我最好的选择是编译器由于递归而崩溃。要么他们还不支持这个,要么是编译器中的一个错误。
  • 为什么需要 C : CalendarUnit 上的日历?你能多解释一下“Second”和“C”在你的实现中是什么意思吗?
  • 我更新了这个问题,是为了能够创建一个日期结构,它可以询问它的日历它代表的秒数。但为了使其更加模块化,每种类型都有自己的初始化程序、逻辑等,而日历将是这些组件类型的持有者。

标签: ios xcode date swift calendar


【解决方案1】:

首先:llvm 抛出分段错误是总是编译器中的一个错误,无论你的语法是否正确,你应该为它填充一个雷达。

关于您的问题:我认为您不需要递归定义。 我认为你可以通过这样的实现来实现你所需要的:

import Foundation

protocol CalendarUnit {
  init<T>(_ date: Date<T>)
}

protocol Calendar {
  typealias Second: CalendarUnit
}

struct GregorianCalendar: Calendar {

  struct Second: CalendarUnit {
      init<T>(_ date: Date<T>) {
          println("Initialized")
      }
  }
}

struct Date<C: Calendar> {
  let timestamp: Int

  var second: C.Second { return C.Second(self) }
}

let test = Date<GregorianCalendar>(timestamp: 0)
let seconds = test.second

【讨论】:

  • 效果很好,非常感谢。我希望 Apple 尽快纠正许多编译器错误,不知道是我还是编译器出现故障令人沮丧。
  • 有没有办法限制CalendarUnit内部init中的T与拥有CalendarUnit的Calendar相同?
  • 只是澄清一下:您能否添加一个示例说明它们何时不同?
  • 您现在遇到的是一个有趣的情况:在您的示例中,您使用的是init&lt;GregorianCalendar&gt;(date: Date&lt;GregorianCalendar&gt;),但想猜猜GregorianCalendar.self 的类型是什么?它实际上是 JulianCalendar 类型!原因是泛型语法采用任何类型的名称。您将其命名为GregorianCalendar,但实际上您可以将其命名为WhateverYouWant(我碰巧将其命名为T)。尝试做:println("\(GregorianCalendar.self is JulianCalendar.Type)") 在您的示例的 CalendarUnit init 中。你会看到那是true
  • 好的,感谢您帮助我理解这一点。可悲的是,为了能够强制执行类型限制,我将不得不等待协议递归被修复。因为这样的事情仍然可能发生: let date = Date() GregorianCalendar.Year(date: date) 无论如何,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 2020-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多