【问题标题】:How do I sort a swift array containing instances of NSManagedObject subclass by an attribute value (date)如何按属性值(日期)对包含 NSManagedObject 子类实例的快速数组进行排序
【发布时间】:2014-12-22 00:53:57
【问题描述】:

我正在尝试按照the accepted answer to this question 中的布局对数组进行排序,但遇到了 Isuru 在该答案的 cmets 中提到的问题。也就是说,应该按实体的“日期”属性对数组进行排序的代码会导致编译器抱怨“找不到成员'日期'”

这里是描述实体的 NSManagedObject 子类:

import Foundation
import CoreData

@objc(Entry)
class Entry: NSManagedObject {

    @NSManaged var date: NSDate
    @NSManaged var reflections: AnyObject
    @NSManaged var contactComment: NSSet
    @NSManaged var person: NSSet

    override func awakeFromInsert() {
        let now:NSDate = NSDate()
        self.date = now;
    }
}

这是尝试对数组进行排序的代码:

lazy var entries:[Entry] = {
    var days:[Entry] = self.managedObjectContext!.requestEntity("Entry")as [Entry]
    days.sort({$0.date < $1.date})

    var today:Entry = days.last!
    println(today.date)
    return days
}()

请注意,在该代码的后半部分,我可以访问并记录其中一个条目的“日期”属性,编译器对此没有任何问题。

我的排序语法是否正确?我没有看到的这段代码还有其他问题吗?

【问题讨论】:

    标签: arrays cocoa sorting core-data swift


    【解决方案1】:

    这部分是 Swift 编译器的问题,它没有给你一个有用的错误。真正的问题是NSDate 不能直接与&lt; 进行比较。相反,您可以使用NSDatecompare 方法,如下所示:

    days.sort({ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending })
    

    或者,您可以扩展NSDate 以实现Comparable 协议,以便可以将其与&lt;(和&lt;=&gt;&gt;===)进行比较:

    public func <(a: NSDate, b: NSDate) -> Bool {
        return a.compare(b) == NSComparisonResult.OrderedAscending
    }
    
    public func ==(a: NSDate, b: NSDate) -> Bool {
        return a.compare(b) == NSComparisonResult.OrderedSame
    }
    
    extension NSDate: Comparable { }
    

    注意:你只需要实现&lt;==和如上所示,那么其余的运算符&lt;=&gt;等将由标准库。

    有了这些,你原来的排序功能应该可以正常工作了:

    days.sort({ $0.date < $1.date })
    

    【讨论】:

    • 这对于少量数据非常有效,但是当您有大量数据时,加载需要一段时间。有没有更有效的方法?
    • @nsij22 因为我们在这里谈论的是NSManagedObjects,那么这些对象可能来自核心数据存储。在这种情况下,最有效的做法可能是通过核心数据获取请求对数据进行排序。看看NSFetchRequest.sortDescriptorsdeveloper.apple.com/library/mac/documentation/Cocoa/Reference/…
    【解决方案2】:

    在 Swift 3 中,日期现在可以直接比较:

    let aDate = Date()
    let bDate = Date()
    
    if aDate < bDate {
    
        print("ok")
    }
    

    老斯威夫特: 另一种方法是对日期对象的 timeIntervalSince1970 属性进行排序,该属性可直接进行比较。

    days.sort({$0.date.timeIntervalSince1970 < $1.date.timeIntervalSince1970})
    

    【讨论】:

    • 我只是在需要同样的东西并且看到接受的答案的第一句话时才想到它,这比发布接受的答案时要晚很多。
    【解决方案3】:

    swift2.1使用这行代码

    array.sortInPlace({ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending })
    

    【讨论】:

      【解决方案4】:

      更新__Swift 4,

      let sortedData = dataToSort.sorted(by: { (obj1, obj2) -> Bool in             
         return obj1.date < obj2. date
      })
      

      【讨论】:

        【解决方案5】:

        我有一本字典,其键是日期格式,所以我必须按日期对字典进行排序。我复制了 nsarray 中的所有键,然后使用以下代码对该数组进行排序。

        let keys : NSArray = stackedBarDataDict.allKeys // stackedBarDataDict is Data Dictionary
            let dataArray = NSMutableArray()
            for index in 0...(stackedBarDataDict.allKeys.count - 1)
            {
                let dateone = keys.objectAtIndex(index)
                let dateFormatter = NSDateFormatter()
                dateFormatter.dateFormat = "yyyy-MM-dd"
                let date1 = dateFormatter.dateFromString(dateone as! String)
                dataArray.addObject(date1!)
            }
            let array : NSArray = (dataArray as NSArray)
                let sortedArray = array.sortedArrayUsingComparator {
                (obj1, obj2) -> NSComparisonResult in
        
                let p1 = obj1 as! NSDate
                let p2 = obj2 as! NSDate
                let result = p1.compare(p2)
                return result
            }
            print(sortedArray)
        

        【讨论】:

          猜你喜欢
          • 2010-11-21
          • 2012-04-24
          • 1970-01-01
          • 1970-01-01
          • 2015-02-24
          • 1970-01-01
          相关资源
          最近更新 更多