iOS:带有日期的数组中的 UICollectionView 部分

iOS: UICollectionView sections from array with dates

我有 arrayPerson。 Person object 之间有许多字段 inscriptionDate (a timestamp)。我必须从这个 array 创建一个 collectionView 但使用 sections。每个部分都有一个 header 即 inscriptionDate 作为具有此格式 dd/mm/yyyy 的日期。我必须按 inscriptionDatearray 进行排序,但没有时间(仅格式 dd/mm/yyyy),以便在 collectionView 中加载数据(考虑到这些部分)。我从另一个问题中发现了这个solution。但是在执行此操作之前如何对 array 进行排序?我该如何使用它:

order = NSCalendar.currentCalendar().compareDate(now, toDate: olderDate, 
            toUnitGranularity: .Day)

就我而言?

假设您的 inscriptionDateDate,您为什么不能对其进行排序?因为 Date 符合 Comparable 你所需要的只是

let sortedByDate = persons.sorted { [=10=].inscriptionDate < .inscriptionDate }

首先,您需要在排序前清理时间戳。您可以使用 CalendarDate 扩展名来做到这一点:

extension Date {
    func noTime() -> Date! {
        let components = Calendar.current.dateComponents([.day, .month, .year], from: self)
        return Calendar.current.date(from: components)
    }
}

然后你只需要按日期排序你的数组而不用时间:

let sortedByDate = persons.sorted { [=11=].inscriptionDate.noTime() < .inscriptionDate.noTime() }

注意。 注意 CalendarcompareDate 函数,因为它只比较特定的组件。如果在此示例中: NSCalendar.currentCalendar().compareDate(now, toDate: olderDate, toUnitGranularity: .Day) 不同月份的日期相同,则比较结果将显示日期相等。

我为你写了一个代码我觉得这个代码对你有用。

//
//  ViewController.swift
//  sortData
//
//  Created by Bijender singh on 26/01/18.
//  Copyright © 2018 Bijender singh. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(_ animated: Bool) {

        let myDataArray = NSMutableArray()
        var myDataDic = NSMutableDictionary()

        myDataDic.setValue("Bijender", forKey: "name")
        myDataDic.setValue("1516965600", forKey: "date")
        myDataArray.add(myDataDic)

        myDataDic = NSMutableDictionary()
        myDataDic.setValue("ben", forKey: "name")
        myDataDic.setValue("1516965540", forKey: "date")
        myDataArray.add(myDataDic)

        myDataDic = NSMutableDictionary()
        myDataDic.setValue("Deke", forKey: "name")
        myDataDic.setValue("1516842180", forKey: "date")
        myDataArray.add(myDataDic)

        myDataDic = NSMutableDictionary()
        myDataDic.setValue("Veer", forKey: "name")
        myDataDic.setValue("1516842000", forKey: "date")
        myDataArray.add(myDataDic)

        myDataDic = NSMutableDictionary()
        myDataDic.setValue("Ashfaq", forKey: "name")
        myDataDic.setValue("1515981900", forKey: "date")
        myDataArray.add(myDataDic)


        print(myDataArray)

        let sortedArray = self.sortDataWithDate(arrayData: myDataArray)

        // sortedArray contane array which contan same date array 
        // you can use it according to you
        // sortedArray.count is total diffrent dates in your array
        // and (sortedArray.count[i] as! NSArray).count give you count of data of that date (0 < i < sortedArray.count)
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func sortDataWithDate(arrayData : NSArray) -> NSArray {
        //  var chat: [ChatMessage]!

        let returnArray = NSMutableArray()
        var subArray = NSMutableArray()
        let arrayDate = NSMutableArray()

        for i in 0 ..< arrayData.count {

            let msgDate = self.timeStampToDate(_timestamp: ((arrayData[i] as! NSDictionary).object(forKey: "date") as! String), _dateFormat: "dd/MM/yyyy")

            print("dddt \(msgDate)")

        //    print("date array \(arrayDate)  $$  msgDate \(msgDate)")
            if arrayDate.contains(msgDate) {

                subArray.add(arrayData[i])

            }
            else{
                arrayDate.add(msgDate)
                if arrayDate.count > 1 {
                    returnArray.add(subArray)
                }

                subArray = NSMutableArray()
                subArray.add(arrayData[i])
            }
        }

        if subArray != nil {
            returnArray.add(subArray)
        }

        print(returnArray)
        return returnArray
    }

     func timeStampToDate(_timestamp : String, _dateFormat : String) -> String{

        // _dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS"

        var date = Date(timeIntervalSince1970: TimeInterval(_timestamp)!)
        date += TimeInterval(Int(TimeZone.current.secondsFromGMT()) as NSNumber)
        let dateFormatter = DateFormatter()
        dateFormatter.timeZone = TimeZone(abbreviation: "GMT") //Set timezone that you want
        dateFormatter.locale = NSLocale.current
        dateFormatter.dateFormat = _dateFormat
        let strDate = dateFormatter.string(from: date)
        return strDate

    }

}

在这段代码中,我插入了硬编码的数组

(
        {
        date = 1516965600;
        name = Bijender;
    },
        {
        date = 1516965540;
        name = ben;
    },
        {
        date = 1516842180;
        name = Deke;
    },
        {
        date = 1516842000;
        name = Veer;
    },
        {
        date = 1515981900;
        name = Ashfaq;
    }
)

输出数组是

(
        (
                {
            date = 1516965600;
            name = Bijender;
        },
                {
            date = 1516965540;
            name = ben;
        }
    ),
        (
                {
            date = 1516842180;
            name = Deke;
        },
                {
            date = 1516842000;
            name = Veer;
        }
    ),
        (
                {
            date = 1515981900;
            name = Ashfaq;
        }
    )
)

我同意@Vasilii Muravev,您需要先清理您的 timestamp 对象,使用扩展或函数。顺便说一句,时间戳不是有效的 Swift 对象,除非它是您创建的自定义 class。

然后你可以为你的数据源创建一个字典。我将使用@Vasilii Muravev 的扩展名:

//var myKeys : [Date] = []
let sortedPeople = persons.sorted { [=10=].inscriptionDate.noTime() < .inscriptionDate.noTime() }
//break your array into a dictionary([Date : [Person]])
//personsSortedByDateInSections : [Date : [Person]] = [:]
for person in sortedPeople {
    if personsSortedByDateInSections[person.inscriptionDate] != nil {
        personsSortedByDateInSections[person.inscriptionDate]!.append(person)
    } else {
        personsSortedByDateInSections[person.inscriptionDate] = [person]
    }
}
myKeys = setKeyArray(personSortedByDateInSections.keys)

这将为您提供一个字典对象,其中所有 Person 对象按 inscriptionDate 分组(分段)。然后您只需要填写您的 collectionView 委托和数据源方法。

override func numberOfSections(in: UICollectionView) -> Int {
    return myKeys.count
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return personsSortedByDateInSections[myKeys[section]].count
}

更新: 正如您的评论中所述,使用 swift 字典获取键数组存在问题(我认为 swift 字典在早期版本中没有这个问题?我可能是错的)... .无论如何要解决这个问题我已经使用这个函数为 'keyArray' 设置了一个 class 变量。:

fileprivate func setKeysArray(_ keys: LazyMapCollection<Dictionary<Date, [Person]>, String) -> [Date]{
    var keysArray = [Date]()

    for key in keys {
        keysArray.append(key)
    }
    return keysArray
}