【问题标题】:Swift - How to initialize a default value for NSDate property?Swift - 如何初始化 NSDate 属性的默认值?
【发布时间】:2015-03-14 01:27:58
【问题描述】:

我有一个简单的类定义:

class Course{

    var date:NSDate

    init(){

    }
}

例如在c#中,当创建此类时,日期属性将具有默认的DateTime.MinValue。

  • 我不想让它成为 NSDate?因为按照我的业务逻辑 这个属性是必须的,并且每门课程都有一个日期。 (设置为 NSDate?意味着课程可以在没有日期的情况下存在)

  • 我不想将其设置为现在,因为它具有误导性。现在可能是 一个有效值,来自我的业务逻辑的其他部分。

我怎样才能在 swift 中做同样的事情?

【问题讨论】:

    标签: swift datetime nsdate default-value


    【解决方案1】:

    如果所有课程都需要有效日期,为什么要创建没有实际日期的课程?摆脱init() 并创建一个指定的初始化程序。

    class Course{
        let date: NSDate
    
        init(date: NSDate) {
            self.date = date
        }
    }
    

    如果您坚持拥有这些奇怪的“非真实约会”,您可以使用distantPast()

    class Course{
        var date: NSDate
    
        init() {
            self.date = NSDate.distantPast() as NSDate
        }
    }
    

    【讨论】:

    • 还有 Date.distantPast
    【解决方案2】:

    您可以像这样为NSDate 创建一个扩展:

    extension NSDate
    {
        class func minimumDate() -> NSDate
        {
            let calendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
            return calendar.dateWithEra(1, year: 1, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0)!
        }
    }
    

    这将允许您使用类似的1/1/0001 00:00:00 时间戳实例化一个新的NSDate

    let myDate = NSDate.minimumDate()
    

    Swift 还有一个 null-coalesce 运算符 (??),它允许您在初始化程序中执行类似的操作:

    class Widget
    {
        var dateCreated : NSDate
    
        init(dateCreated: NSDate?)
        {
            self.dateCreated = dateCreated ?? NSDate.minimumDate()
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果你总是在init 方法中初始化date(如果如你所说,它必须有一个日期),那么下面的就可以了:

      class Course {    
          var date: Date          // if Swift 2 we’d use `NSDate`, but in Swift 3 and later, we’d use `Date`
      
          init() {
              date = ... // set it to some reasonable, default value
          }
      }
      

      或者,如果没有合理的默认值,您可以指定一个初始化器来提供该值:

      class Course {    
          var date: Date
      
          init(date: Date) {
              self.date = date
          }
      }
      

      但是,如果在实例化对象时无法指定值并且只能在稍后的某个时间点设置日期,但它应该始终具有从该时间点开始的值,则可以使用隐式展开的可选项.正如 the documentation 隐式展开的选项所说:

      有时从程序的结构中可以清楚地看出,在第一次设置该值之后,可选项将始终具有一个值。在这些情况下,无需在每次访问可选值时检查和解开它的值,因为可以安全地假定它始终具有值。

      这些类型的可选项被定义为隐式未包装的可选项。您可以通过在类型后放置感叹号 (String!) 而不是问号 (String?) 来编写隐式未包装的可选项您想将其设为可选。

      因此,您将拥有

      class Course {
          var date: Date!
      
          init() {
              // the `date` is not necessarily set here, but once it is set, it shouldn't be `nil` thereafter
          }
      }
      

      是的,从技术上讲,通过隐式展开可选,date 可能是 nil,但实践是,如果它最初可能是 nil,但一旦设置,它将永远不会再是 nil,你会使用隐式包装的可选。

      【讨论】:

      • 这会起作用,但我认为这是不适合隐式展开的可选项(又名“感叹号值”)的情况。 init 应该设置它。
      • 我同意。 OP 的场景中散发出一股代码味道,即 (a) 每个 Course 必须 都有一个日期;但也暗示(b)他想创建一个Course,同时既不提供date 值,也没有任何有意义的默认值。但是,有时我们必须这样做(在这些情况下,隐式展开的选项是正确的解决方案),但我同意像这样的简单模型对象很少属于该类别。但是使用像distantPast 这样的默认标记值,只是为了避免使用可选值,是一种根本上存在缺陷的方法。
      猜你喜欢
      • 2014-10-15
      • 1970-01-01
      • 2015-04-08
      • 2020-11-29
      • 1970-01-01
      • 2014-11-22
      • 1970-01-01
      • 1970-01-01
      • 2014-12-29
      相关资源
      最近更新 更多