【问题标题】:How to load JSON Data into FSCalendar Swift 5如何将 JSON 数据加载到 FSCalendar Swift 5
【发布时间】:2021-04-12 11:27:10
【问题描述】:

我正在尝试将我的 JSON 数据加载到 FSCalendar。

我从文档中了解到,当您使用可以用点显示在日历中的数组时。我想做同样的事情,而是让点出现在我的 JSON 文件中列出的日期中。我已经将 JSON 文件加载到我的包中,并创建了一个函数来加载 JSON 数据,并且我已经创建了一个结构。

当我尝试使用结构中的数组然后将该数组加载到“func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {”函数中时,我的问题就出现了。我已经为此工作了一段时间,可以使用一些帮助。谢谢

JSON 数据:- 我将 JSON 文件命名为 data.json

[               
    {
        "event": "Christmas",
        "date": [
            "2021-01-02",
            "2021-01-03",
            "2021-01-04"
        ]
                                        
    }
]

视图控制器:

import UIKit
import FSCalendar

class ViewController: UIViewController, FSCalendarDelegate, FSCalendarDataSource, FSCalendarDelegateAppearance {
    
    //MARK: - calendar variables
    @IBOutlet var calendar: FSCalendar!
    @IBOutlet weak var dateLabel: UILabel!
    
    
    fileprivate let gregorian: Calendar = Calendar(identifier: .gregorian)
    
    fileprivate lazy var dateFormatter1: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy/MM/dd"
        return formatter
    }()
    fileprivate lazy var dateFormatter2: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
    
// These are just test data to see the dots on the calendar
    var datesWithEvents = ["2021-01-15","2021-01-16","2021-01-17","2021-01-18"]
    var datesWithMultipleEvents = ["2021-01-20","2021-01-21","2021-01-22","2021-01-23"]
    

    //MARK: - JSON variable
//    var result: Results?

    let data = DataLoader().eventData
    
    

    //MARK: - viewdidload
    override func viewDidLoad() {
        super.viewDidLoad()
        
       // parseJSON()
        let data = DataLoader().eventData
        
        print(data)
        

        calendar.delegate = self
        calendar.dataSource = self
    }
    
    deinit {
        print("\(#function)")
    }
    
    
    
    //MARK: - calendar functions
    
    func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
        let formatter = DateFormatter()
        formatter.dateFormat = "EEEE MM-dd-YYYY"
        let string = formatter.string(from: date)
        print("\(string)")
        
        
    }
    
    func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, eventDefaultColorsFor date: Date) -> [UIColor]? {
        let key = self.dateFormatter2.string(from: date)


// this is the test with the hard coded arrays, I think i need to 
implement the JSON here but am not sure how
        if self.datesWithMultipleEvents.contains(key) {
            return [UIColor.magenta, appearance.eventDefaultColor, UIColor.red]
        }
        return nil
    }
    
    
    func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
        let dateString = self.dateFormatter2.string(from: date)

        if self.datesWithEvents.contains(dateString) {
            return 1
        }
        if self.datesWithMultipleEvents.contains(dateString) {
            return 3
        }
        return 0
    }

数据模型:

struct EventsData: Codable {
    
    var event: String
    var date: [String]
}

JSON 加载器:

import Foundation

public class DataLoader {
    
    @Published var eventData = [EventsData]()
    
    init() {
        load()
    }
    
    func load() {
    
        if let fileLocation = Bundle.main.url(forResource: "data", withExtension: "json") {
            
            //do catch incase of error
            do {
                let data = try Data(contentsOf: fileLocation)
                let jsonDecoder = JSONDecoder()
                let dataFromJson = try jsonDecoder.decode([EventsData].self, from: data)
                
                self.eventData = dataFromJson
                
            } catch {
                print(error)
            }
            
        }
    }
}

编辑:

func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
    let dateString = self.dateFormatter2.string(from: date)
    
    if self.eventData.contains(where: //<#T##(EventsData) throws -> Bool#>) //How to get this to do the contains like in the next if statement
    

    if self.datesWithEvents.contains(dateString) {
        return 1
    }
    if self.datesWithMultipleEvents.contains(dateString) {
        return 3
    }
    return 0
}

【问题讨论】:

  • 你为什么使用硬编码数组,为什么方法返回硬编码值?还有你为什么要使用@Published,这看起来不像 SwiftUI 代码?
  • @joakimDanielson 硬编码数组仅用于测试。我没有在实际数据中使用它们。它们来自文档。此外,我只是使用已发布,因为我在 JSON 的教程中看到它,看看它是否有所作为。我主要关心的是如何从该 JSON 中获取数据以在日历中显示信息。我错过了什么?谢谢
  • @JoakimDanielson 我更新了问题
  • 我认为 load() 方法应该返回一个数组而不是把它分配给一个属性。
  • @JoakimDanielson var eventData = [EventsData]() 不是将从显示 JSON 数据的结构中加载我的数据的数组吗?还是我还需要将 JSON 中的数据附加到该数组中?

标签: ios json swift fscalendar


【解决方案1】:

检查你的代码中是否有这个:

// FSCalendarDataSource
func calendar(calendar: FSCalendar!, hasEventForDate date: NSDate!) -> Bool {
    return shouldShowEventDot
}

【讨论】:

  • 当我添加它告诉我没有 shouldShowEventDot
  • 对...因为你需要声明它或者想出你自己的标志来返回
【解决方案2】:

只需使用 DateFormatter 将您的字符串日期转换为日期,然后检查您的数组并检查日期(来自日历函数)是否与您在活动中的任何日期匹配。

【讨论】:

  • 我需要遍历数组吗?
  • @MattyJay94 是的
【解决方案3】:

你有很多问题。

首先,您尝试在 Swift 应用程序中使用 SwiftUI 构造 (@Published)。那是行不通的。

其次,您的日期以字符串数组的形式出现。我建议使用自定义的Date 解码策略设置您的 Codable 协议一致性。

This link 展示了如何设置您的 JSONDecoder 以使用采用自定义 DateFormatter 的自定义日期解码策略。

接下来,当从 JSON 输入读取新数据时,您需要一些方法来更新 UI。 SwiftUI 有自动响应状态变化的内置机制,但你没有使用 SwiftUI,所以这些不适用。

您有一个加载 JSON 数据的 DataLoader 类。它目前从文件中同步读取硬编码的 JSON。我假设您想从 Internet 加载数据,这将是异步的。因此你的方法行不通。

我建议您设置您的 DataLoader 类,使其在完成加载新数据时通知它的委托,或者将其设置为使用完成处理程序接受请求。

如果您不知道如何做这两件事,那么您需要停下来学习一些基础知识。在继续之前阅读 Swift 异步网络、完成处理程序和委托设计模式。

【讨论】:

  • 感谢您的回复。但我已经找到了答案,并将把正确的信息上传到这篇文章中。我发现很少有关于使用数据库实现 FScalendar 的完整教程。所以我想我会做一个。干杯
猜你喜欢
  • 2021-09-26
  • 2016-12-28
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 2016-09-19
  • 1970-01-01
相关资源
最近更新 更多