【问题标题】:How can I filter by specific date from realm object in swift?如何在 swift 中按特定日期从领域对象中过滤?
【发布时间】:2020-03-07 12:22:50
【问题描述】:

我有一个日期属性类型为 Date 的领域对象,并且想要获取具有特定日期的项目列表。

如果我点击日历中的特定日期,例如 2020-03-06 ,那么它将显示在 2020-03-06 创建的项目列表。

:: 已编辑 ::

这是我的名为“Profile”的领域对象,日期从 2020-03-05 至 2020-03-08 .

这是我的 Profile 对象和 ProfileManager Singleton。

class Profile: Object {
    @objc dynamic var date: Date!
    @objc dynamic var content: String!

    convenience init(_ content: String) {
        self.init()
        self.content = content
        self.date = Date()
    }
}


class ProfileManager {

    static let shared = ProfileManager()

    private var realm = try! Realm()

    var profileList: Results<Profile>?

    private init() {
        profileList = realm.objects(Profile.self)
    }

    func save(_ object: Profile) {
        do {
            try realm.write {
                realm.add(object)
            }
        } catch {
            print(error)
        }
    }

    func addNewProfile(_ content: String) {
        let newProfile = Profile(content)
        save(newProfile)
    }
}

最后,这是一个带有按钮的 viewController。一为 添加新配置文件,以及一个用于打印过滤配置文件列表的配置文件。

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func addProfilePressed(_ sender: Any) {
        ProfileManager.shared.addNewProfile("profile content")
    }

    @IBAction func filterButtonPressed(_ sender: Any) {
        let stringDate = "2020-03-09"
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let searchDate:Date = dateFormatter.date(from: stringDate)!
        let results = ProfileManager.shared.profileList!.filter("date == %@", searchDate)
        print(searchDate)
        print(results)
        for profile in results {
            print(profile.content!)
        }
    }
}

调用 filterButtonPressed 方法时控制台上的结果。

2020-03-08 15:00:00 +0000
Results<Profile> <0x7f9b36f160a0> (

)

我该如何解决这个问题? 这是另一个问题。 我将“stringDate”的值设置为“2020-03-09” 但是当我打印转换日期 'searchDate' 时,它会打印“2020-03-08” 为什么会这样?

希望现在我的问题更容易理解。

【问题讨论】:

  • 请在问题中发布代码,而不是图像。
  • @Willeke 好的,完成。
  • 我将您编辑的代码复制并粘贴到一个项目中,它工作正常。但是,请注意您正在搜索 let stringDate = "2020-03-09",并且该日期为 09 的日期在问题中显示的数据集中不存在,因此不会有任何结果。
  • @Jay 很奇怪,使用相同的代码,它对你有用,对我不起作用。我知道没有 09 天,我尝试了任何数字和相同的结果。当我输入数字时,它会在 stringDate 前一天打印。在这种情况下,它会打印我 2020-03-08 .. 无论如何都想解决这个问题,但不知道......
  • 等一下。我复制了它。让我回复你。

标签: swift date filter realm


【解决方案1】:

我原来的答案在下面,经过大量研究后,只是有点正确。

实际答案与日期的时间戳部分有关。

所以...如果我们使用以下代码创建一个日期对象并将其设置为已知日期,

let stringDate = "2020-03-08"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!

实际的对象看起来像这样

2020-03-08T05:00:00.000Z

但是,Profile 对象的创建方式是这样的

convenience init(_ content: String) {
   self.init()
   self.content = content
   self.date = Date()
}

那个日期对象看起来像这样

2020-03-08T16:10:25.123Z

如您所见,如果我们针对特定日期进行过滤,则这些日期不相等

2020-03-08T05:00:00.000Z != 2020-03-08T16:10:25.123Z

这就是为什么

let stringDate = "2020-03-08"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let searchResults = realm.objects(Profile.self).filter("date == %@", searchDate)

找不到日期,因为它正在为此过滤

2020-03-08T05:00:00.000Z

要修复,请使用带有默认时间戳的日期戳更改配置文件类

class Profile: Object {

    @objc dynamic var date: Date!
    @objc dynamic var content: String!

    convenience init(_ content: String) {
        self.init()
        self.content = content

        let formatter = DateFormatter()
        formatter.timeStyle = .none
        formatter.dateFormat = "MM/dd/yy"

        let today = Date()
        let s = formatter.string(from: today)
        let d = formatter.date(from: s)

        self.date = d
    }
}

或者,将您的日期存储为字符串 yyyymmdd,这将完全消除歧义。

-- 下面是原始答案 ---

日期对象完全支持按日期过滤。这里有两个简单的例子。一个用于过滤特定日期(针对您的问题),另一个用于使用 BETWEEN 的日期范围。

注意,我有一个函数 makeDate 将字符串转换为日期对象。此示例使用具有 dog_birthdate 日期属性的 Realm DogClass 对象。


这会过滤具有特定日期的对象

let searchDate = self.makeDate(fromString: "06/01/2019")
let specificDateResults = realm.objects(DogClass.self)
                               .filter("dog_birthdate == %@", searchDate)
for dog in specificDateResults {
    print(dog.dog_name)
}

这会过滤一个日期范围内的对象

let startDate = self.makeDate(fromString: "06/01/2019")
let endDate = self.makeDate(fromString: "06/20/2019")
let dateRangeResuls = realm.objects(DogClass.self)
                           .filter("dog_birthdate BETWEEN {%@,%@}", startDate, endDate)
for dog in dateRangeResuls {
    print(dog.dog_name)
}

编辑:使用 OP 评论中的代码进行测试

let stringDate = "2019-06-01"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let result = realm.objects(DogClass.self).filter("dog_birthdate == %@", searchDate)
for dog in result {
    print(dog.dog_name)
}

效果很好。

【讨论】:

  • 感谢您的回复。我尝试测试下面的代码并打印此列表,让 stringDate = "2020-03-07" let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let searchDate:Date = dateFormatter.date(from:字符串日期)! realm.objects(T.self).filter("date == %@", searchDate) 但它向我显示了一个空列表。结果 ( )
  • @alphonse 请查看我的答案的编辑。我将您评论中的代码复制并粘贴到我的项目中,将您评论中的字段从date 更改为dog_birthdate 以匹配我的对象结构并添加let result = realm...。它适用于这些更改。哦,删除了 T.self,因为我不知道 T 是什么,并替换了我的 DogClass 名称
  • 我使用另一个名为“content”的领域对象属性进行了测试,该属性的类型是字符串。有一个项目包含字符串“香蕉”。和 realm.objects(T.self).filter("content == %@", "Banana") 使用此代码,它向我显示带有 Banana 的项目。但是为什么它不适用于日期类型?
  • @alphonse 我不知道,因为您评论中的代码对我有用,如我的回答所示。我注意到有人投票结束您的问题 - 可能是因为它不包含任何代码。也许你可以用你的 Realm 模型和你当前使用的代码来更新你的问题——它对我有用,所以你必须做一些不同的事情,并且检查问题中的代码比在 cmets 中更容易。
  • 是的,我认为我的领域对象有问题。我会尝试修复它。无论如何,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多