I am using collection view for displaying result.I want to delete particular cell when that cell is selected. To keep record of selected cell, i am using struct.Everything is working perfectly. But when i click delete button selected cell are not getting deleted.Some other cell gets deleted. But when i go back to the previous screen and come back again ,the cell which i wanted to be deleted is actually removed. I don't know why and how this is happening?
import UIKit
import GRDBCipher
class AdvisoryViewController:
UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {
#IBOutlet weak var new_advisory_label: UILabel!
var getname=String()
var array=[String]()
var date_array=[String]()
var crop_code:String=""
var dbQueue:DatabaseQueue? = nil
var ss = [Int]()
var struct_array :[myObject] = []
var msg_stat:[oldMsg] = []
var msg_count_array=[Int]()
var msg_array=[String]()
var selected_date_array=[String]()
var srno_array=[String]()
var selected_srno_array=[String]()
#IBOutlet weak var collection_view: UICollectionView!
struct myObject
{
var date: String
var advisory:String
var status: String
var srno: String
}
struct oldMsg
{
var is_checked: Bool
}
override func viewDidLoad() {
super.viewDidLoad()
do{
let longpress1=UILongPressGestureRecognizer(target: self, action: #selector(longpress))
// longpress1.minimumPressDuration=1
collection_view.addGestureRecognizer(longpress1)
let
path=NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,
true).first!
dbQueue = try DatabaseQueue(path: "\(path)/pest_messenger.sqlite")
try dbQueue?.inDatabase { db in
let crop_sursor = try Row.fetchCursor(db, "SELECT * FROM crop_master where crop_name='\(getname)'")
while let row = try crop_sursor.next() {
let title: String = row.value(named: "srno")
crop_code=title
}
let rows = try Row.fetchCursor(db, "SELECT distinct brief_advisory,advisory_date,srno FROM crop_insect_advisory_issued where crop_code='\(crop_code)'")
while let row = try rows.next() {
let title: String = row.value(named: "brief_advisory")
let da:String=row.value(named:"advisory_date")
let srno:Int = row.value(named:"srno")
let date_f=DateFormatter()
date_f.dateFormat="yyyy-MM-dd"
let d=date_f.date(from: da)
date_f.dateFormat="dd-MM-yyyy"
let dd=date_f.string(from: d!)
array.append(title)
date_array.append(dd)
srno_array.append("\(srno)")
}
}
for i in 0 ..< array.count
{
struct_array.append(myObject(date:date_array[i],advisory:array[i],
status:"N",srno:srno_array[i]))
}
for i in 0 ..< array.count
{
msg_stat.append(oldMsg(is_checked: false))
}
collection_view.delegate = self
collection_view.dataSource = self
}catch{
print(error)
}
}
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt
indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
"AdvisoryCollectionViewCell", for: indexPath) as!
AdvisoryCollectionViewCell
cell.msg_label.text = struct_array[indexPath.item].advisory
cell.date_label.text = struct_array[indexPath.item].date
let imagee = UIImage.init(named: "rsz_tick")
cell.check_image.image = imagee
cell.check_image.isHidden = true
if( msg_stat[indexPath.row].is_checked == false){
cell.check_image.isHidden = true
}
else if(msg_stat[indexPath.row].is_checked == true)
{
cell.check_image.isHidden = false
}
else{
}
return cell
}
func longpress(gestureRecognizer: UIGestureRecognizer)
{
let righbarButton = UIBarButtonItem(image: UIImage(named:
"rsz_delete")?.withRenderingMode(.alwaysOriginal), style:
UIBarButtonItemStyle.plain, target: self, action:
#selector(myRightTapped(sender:)))
self.navigationItem.rightBarButtonItem = righbarButton
let longpress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longpress.state
let locationInview = longpress.location(in: collection_view)
var indexpath=collection_view.indexPathForItem(at: locationInview)
if(gestureRecognizer.state == UIGestureRecognizerState.began)
{
let cell = collection_view.cellForItem(at: indexpath!) as!
AdvisoryCollectionViewCell
cell.check_image.isHidden = false
msg_stat[(indexpath?.row)!].is_checked = true
ss.append((indexpath?.item)!)
print("index of deleting = \(indexpath?.item)")
msg_count_array.append((indexpath?.item)!)
msg_array.append(struct_array[(indexpath?.item)!].advisory)
selected_date_array.append(struct_array[(indexpath?.item)!].date)
selected_srno_array.append(struct_array[(indexpath?.item)!].srno)
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt
indexPath: IndexPath) {
let cell = collection_view.cellForItem(at: indexPath)
as!AdvisoryCollectionViewCell
if(!(ss.isEmpty)){
cell.check_image.isHidden = !cell.check_image.isHidden
if(cell.check_image.isHidden == true)
{
msg_stat[indexPath.row].is_checked = false
print("why removing.....")
if(!(msg_count_array.isEmpty)){
msg_count_array.remove(at: (indexPath.item))}
if(!(msg_array.isEmpty)){
msg_array.remove(at: (indexPath.item))
}
if(!(selected_srno_array.isEmpty))
{
selected_srno_array.remove(at: (indexPath.item))
}
if(!(selected_date_array.isEmpty))
{
selected_date_array.remove(at: (indexPath.item))
}
}
else{
msg_stat[indexPath.row].is_checked = true
msg_count_array.append((indexPath.item))
msg_array.append(array[(indexPath.item)])
selected_srno_array.append(struct_array[(indexPath.item)].srno)
}
}
}
func myRightTapped(sender:UIBarButtonItem!)
{
do{
for i in 0 ..< msg_count_array.count
{
struct_array.remove(at: i)
msg_stat.remove(at: i)
}
msg_count_array.removeAll()
for i in 0 ..< msg_array.count
{
var msg = msg_array[i]
var srno = selected_srno_array[i]
let
path=NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,
true).first!
let dbQueue = try DatabaseQueue(path: "\(path)/pest_messenger.sqlite")
try dbQueue.inDatabase { db in
try db.execute("DELETE FROM crop_insect_advisory_issued where srno='\
(srno)'")
}
}
msg_array.removeAll()
array.removeAll()
date_array.removeAll()
srno_array.removeAll()
// let dbQueue = try DatabaseQueue(path: "\(path)/p_messenger.sqlite")
try dbQueue?.inDatabase { db in
let rows = try Row.fetchCursor(db, "SELECT distinct brief_advisory,advisory_date,srno FROM crop_insect_advisory_issued where crop_code='\(crop_code)'")
while let row = try rows.next() {
let title: String = row.value(named: "brief_advisory")
let da:String=row.value(named:"advisory_date")
let srno:Int = row.value(named:"srno")
let date_f=DateFormatter()
date_f.dateFormat="yyyy-MM-dd"
let d=date_f.date(from: da)
date_f.dateFormat="dd-MM-yyyy"
let dd=date_f.string(from: d!)
array.append(title)
date_array.append(dd)
srno_array.append("\(srno)")
}
}
for i in 0 ..< array.count
{
struct_array.append(myObject(date:date_array[i],advisory:array[i],
status:"N",srno:srno_array[i]))
}
for i in 0 ..< array.count
{
msg_stat.append(oldMsg(is_checked: false))
}
collection_view.reloadData()
}
catch{
print(error)
}
}
}
Related
I am using two collectionViews in my view controller. 1 has a custom layout and custom attributes for its supplementary views.
Here is the view controller:
class ProgressViewController: UIViewController {
private lazy var data = fetchData()
private lazy var recordsDataSource = makeRecordsDataSource()
private lazy var timelineDataSource = makeTimelineDataSource()
fileprivate typealias RecordsDataSource = UICollectionViewDiffableDataSource<YearMonthDay, TestRecord>
fileprivate typealias RecordsDataSourceSnapshot = NSDiffableDataSourceSnapshot<YearMonthDay, TestRecord>
fileprivate typealias TimelineDataSource = UICollectionViewDiffableDataSource<TimelineSection,YearMonthDay>
fileprivate typealias TimelineDataSourceSnapshot = NSDiffableDataSourceSnapshot<TimelineSection,YearMonthDay>
private var timelineMap = TimelineMap()
private var curItemIndex = 0
private var curRecordsOffset: CGFloat = 0
private var curTimelineOffset: CGFloat = 0
private var timelineStart: Date?
#IBOutlet var recordsCollectionView: UICollectionView!
#IBOutlet var timelineCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
data = fetchData()
timelineStart = Array(data.keys).first?.date
configureRecordsDataSource()
configureTimelineDataSource()
configureTimelineSupplementaryViews()
applyRecordsSnapshot()
applyTimelineSnapshot()
if let collectionViewLayout = timelineCollectionView.collectionViewLayout as? TimelineLayout {
collectionViewLayout.delegate = self
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var i: CGFloat = 0
for _ in data {
let recordOffset = self.recordsCollectionView.frame.width * i
let timelineOffset = (timelineCollectionView.frame.width + CGFloat(10)) * i
timelineMap.set(recordOffset: recordOffset, timelineOffset: timelineOffset)
i += 1
}
}
private func fetchData() -> [YearMonthDay:[TestRecord]] {
var data: [YearMonthDay:[
TestRecord]] = [:]
var testRecords:[TestRecord] = []
for i in 0...6{
let testRecord = TestRecord(daysBack: i*2, progression: 0)
testRecords.append(testRecord)
}
for record in testRecords {
let ymd = YearMonthDay(date:record.timeStamp,records: [])
if var day = data[ymd] {
day.append(record)
} else {
data[ymd] = [record]
}
}
return data
}
extension ProgressViewController {
//RECORDS data
fileprivate func makeRecordsDataSource() -> RecordsDataSource {
let dataSource = RecordsDataSource(
collectionView: recordsCollectionView,
cellProvider: { (collectionView, indexPath, testRecord) ->
UICollectionViewCell? in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RecordCollectionViewCell.identifier, for: indexPath) as? RecordCollectionViewCell
cell?.configure(with: testRecord)
return cell
})
return dataSource
}
func configureRecordsDataSource() {
self.recordsCollectionView.register(RecordCollectionViewCell.nib, forCellWithReuseIdentifier: RecordCollectionViewCell.identifier)
}
func applyRecordsSnapshot() {
// 2
var snapshot = RecordsDataSourceSnapshot()
for (ymd,records) in data {
snapshot.appendSections([ymd])
snapshot.appendItems(records,toSection: ymd)
}
recordsDataSource.apply(snapshot, animatingDifferences: false)
}
}
extension ProgressViewController {
enum TimelineSection {
case main
}
fileprivate func makeTimelineDataSource() -> TimelineDataSource {
let dataSource = TimelineDataSource(
collectionView: self.timelineCollectionView,
cellProvider: { (collectionView, indexPath, testRecord) ->
UICollectionViewCell? in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TimelineDayCell.identifier, for: indexPath) as? TimelineDayCell
cell?.backgroundColor = .orange
cell?.dayLabel.text = String(indexPath.section)+","+String(indexPath.row)
return cell
})
return dataSource
}
func configureTimelineDataSource() {
self.timelineCollectionView!.register(TimelineDayCell.nib, forCellWithReuseIdentifier: TimelineDayCell.identifier)
timelineCollectionView.register(
UINib(nibName: "MonthHeader", bundle: nil),
forSupplementaryViewOfKind: TimelineLayout.Element.month.kind,
withReuseIdentifier: TimelineLayout.Element.month.id)
timelineCollectionView.register(
UINib(nibName: "TimelineDayCell", bundle: nil),
forSupplementaryViewOfKind: TimelineLayout.Element.day.kind,
withReuseIdentifier: TimelineLayout.Element.day.id)
timelineCollectionView.register(
UINib(nibName: "YearLabel", bundle: nil),
forSupplementaryViewOfKind: TimelineLayout.Element.year.kind,
withReuseIdentifier: TimelineLayout.Element.year.id)
}
func applyTimelineSnapshot(animatingDifferences: Bool = false) {
// 2
var snapshot = TimelineDataSourceSnapshot()
snapshot.appendSections([.main])
snapshot.appendItems(Array(data.keys))
timelineDataSource.apply(snapshot, animatingDifferences: animatingDifferences)
}
func configureTimelineSupplementaryViews(){
timelineDataSource.supplementaryViewProvider = { (
collectionView: UICollectionView,
kind: String,
indexPath: IndexPath) -> UICollectionReusableView? in
switch kind {
case TimelineLayout.Element.month.kind:
let supplementaryView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TimelineLayout.Element.month.id, for: indexPath)
if let monthLabelView = supplementaryView as? MonthHeader {
let active = Calendar.current.date(byAdding: .month, value: indexPath.item, to: self.timelineStart!)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM"
let monthString = dateFormatter.string(from: active!)
monthLabelView.monthLabel.text = monthString
}
return supplementaryView
case TimelineLayout.Element.year.kind:
let supplementaryView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TimelineLayout.Element.year.id, for: indexPath)
if let yearLabelView = supplementaryView as? YearLabel {
let labelDate = Calendar.current.date(byAdding: .year, value: indexPath.item, to: self.timelineStart!)!
let year = Calendar.current.component(.year, from: labelDate)
yearLabelView.yearLabel.text = String(year)
}
return supplementaryView
default:
fatalError("This should never happen!!")
}
}
}
}
extension ProgressViewController: TimelineLayoutDelegate {
func collectionView(_ collectionView: UICollectionView, dateAtIndexPath indexPath: IndexPath) -> Date? {
return timelineDataSource.itemIdentifier(for: indexPath)?.date
}
}
Then in my custom TimelineLayout I have
class TimelineLayout: UICollectionViewLayout {
weak var delegate: TimelineLayoutDelegate!
enum Element: String {
case day
case month
case year
var id: String {
return self.rawValue
}
var kind: String {
return "Kind\(self.rawValue.capitalized)"
}
}
private var oldBounds = CGRect.zero
private var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
private var contentWidth = CGFloat()
private var cache = [Element: [IndexPath: UICollectionViewLayoutAttributes]]()
private var monthHeight: CGFloat = 19
private var yearHeight: CGFloat = 11
private var dayHeight: CGFloat = 30
private var cellWidth: CGFloat = 2.5
private var collectionViewStartY: CGFloat {
guard let collectionView = collectionView else {
return 0
}
return collectionView.bounds.minY
}
private var collectionViewHeight: CGFloat {
return collectionView!.frame.height
}
override public var collectionViewContentSize: CGSize {
return CGSize(width: contentWidth, height: collectionViewHeight)
}
}
extension TimelineLayout {
override public func prepare() {
guard let collectionView = collectionView,
cache.isEmpty else {
return
}
collectionView.decelerationRate = .fast
updateInsets()
cache.removeAll(keepingCapacity: true)
cache[.year] = [IndexPath: UICollectionViewLayoutAttributes]()
cache[.month] = [IndexPath: UICollectionViewLayoutAttributes]()
cache[.day] = [IndexPath: UICollectionViewLayoutAttributes]()
oldBounds = collectionView.bounds
var timelineStart: Date?
var timelineEnd: Date?
for item in 0 ..< collectionView.numberOfItems(inSection: 0) {
let cellIndexPath = IndexPath(item: item, section: 0)
guard let cellDate = delegate.collectionView(collectionView, dateAtIndexPath: cellIndexPath) else {
return
}
if item == 0 {
let firstDate = cellDate
timelineStart = Calendar.current.startOfDay(for: firstDate)
}
if item == collectionView.numberOfItems(inSection: 0) - 1 {
timelineEnd = cellDate
}
let startX = CGFloat(cellDate.days(from: timelineStart!)) * cellWidth
let dayCellattributes = UICollectionViewLayoutAttributes(forCellWith: cellIndexPath)
dayCellattributes.frame = CGRect(x: startX, y: collectionViewStartY + yearHeight + monthHeight, width: cellWidth, height: dayHeight)
cache[.day]?[cellIndexPath] = dayCellattributes
contentWidth = max(startX + cellWidth,contentWidth)
}
///TODO - what if there are no items in the section....
guard let monthStart = timelineStart?.startOfMonth(), let monthEnd = timelineEnd?.endOfMonth() else { return }
let begin = Calendar.current.date(byAdding: .month, value: -4, to: monthStart)
let end = Calendar.current.date(byAdding: .month, value: 4, to: monthEnd)
var date: Date = begin!
let initalOffset = CGFloat((timelineStart?.days(from: date))!) * cellWidth
var monthOffset: CGFloat = 0
var monthIndex: Int = 0
var yearIndex: Int = 0
while date <= end! {
let daysInMonth = Calendar.current.range(of: .day, in: .month, for: date)?.count
let monthWidth = cellWidth * CGFloat(daysInMonth!)
//let monthIndex = date.months(from: timelineStart!)
let monthLabelIndexPath = IndexPath(item: monthIndex, section: 0)
let monthLabelAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: Element.month.kind, with: monthLabelIndexPath)
let startX = monthOffset - initalOffset
monthLabelAttributes.frame = CGRect(x: startX, y: collectionViewStartY + yearHeight, width: monthWidth, height: monthHeight)
print(startX,"spaghet")
cache[.month]?[monthLabelIndexPath] = monthLabelAttributes
monthOffset += monthWidth
if Calendar.current.component(.month, from: date) == 1 || yearIndex == 0 {
//draw year
//let year = Calendar.current.component(.year, from: date)
//let yearIndex = date.years(from: timelineStart!)
let daysFromStartOfYear = date.days(from: date.startOfYear())
let startYearX = startX - CGFloat(daysFromStartOfYear) * cellWidth
let yearLabelIndexPath = IndexPath(item: yearIndex, section: 0)
let yearLabelAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: Element.year.kind, with: yearLabelIndexPath)
yearLabelAttributes.frame = CGRect(x: startYearX, y: collectionViewStartY, width: CGFloat(30), height: yearHeight)
cache[.year]?[yearLabelIndexPath] = yearLabelAttributes
yearIndex += 1
}
date = Calendar.current.date(byAdding: .month, value: 1, to: date)!
monthIndex += 1
}
}
}
extension TimelineLayout {
public override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
switch elementKind {
case Element.year.kind:
return cache[.year]?[indexPath]
default:
return cache[.month]?[indexPath]
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
visibleLayoutAttributes.removeAll(keepingCapacity: true)
if let yearAttrs = cache[.year], let monthAttrs = cache[.month], let dayAttrs = cache[.day] {
for (_, attributes) in yearAttrs {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
for (_, attributes) in monthAttrs {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
for (_, attributes) in dayAttrs {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
// visibleLayoutAttributes.append(self.shiftedAttributes(from: attributes))
}
}
return visibleLayoutAttributes
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let attributes = cache[.day]?[indexPath] else { fatalError("No attributes cached") }
return attributes
// return shiftedAttributes(from: attributes)
}
override public func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
if oldBounds.size != newBounds.size {
cache.removeAll(keepingCapacity: true)
}
return true
}
override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {
if context.invalidateDataSourceCounts { cache.removeAll(keepingCapacity: true) }
super.invalidateLayout(with: context)
}
}
As you can see I do create timelineDataSource supplementary View Provider in the view controller. Then in the Timeline Layout I implement layoutAttributesForElements(in rect: CGRect) and layoutAttributesForSupplementaryView(ofKind .... The latter never gets called - the error comes first. layoutAttributesForElements(in rect: CGRect) does get called and filled with dayAttrs, monthAttrs, and yearAttrs. However still, the error occurs afterwards:
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: self.supplementaryViewProvider || (self.supplementaryReuseIdentifierProvider && self.supplementaryViewConfigurationHandler)'
terminating with uncaught exception of type NSException
What am I missing?
Edit: I want to add the detail that when I put a breakpoint in that supplementaryViewProvider it's never called. So maybe I am doing something wrong in layoutAttributesForElements(in Rect?)
UICollectionView is running before data(finalAllItems) is populated from web api. I should show UICollectionView with data. I have added below line end of the convertReturnsInToWantedType function. But it did not fix the problem. outletForTheCollectionView.reloadData() How can I show data in UICollectionView?
import UIKit
class HomeViewController: UIViewController {
#IBOutlet weak var outletForTheCollectionView: UICollectionView!
#IBOutlet weak var outletForThePageController: UIPageControl!
var howmanyWords : Int = 0
var dataList : [[String:Any]]?
var finalAllItems = [AllItems]()
override func viewDidLoad() {
super.viewDidLoad()
loadVerbs()
outletForTheCollectionView.delegate = self
outletForTheCollectionView.dataSource = self
let xib = UINib(nibName: "CustomCell", bundle: nil)
self.outletForTheCollectionView.register(xib, forCellWithReuseIdentifier: "ViewCellID")
}
func loadVerbs ()
{
let urlString = "http://somelink/english/vocabularyVerbs.ashx"
let url = URL(string: urlString)
let request = URLRequest(url: url!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0)
let task = URLSession.shared.dataTask(with: request)
{
(data, response, error) in
if let result = try? JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [[String:Any]]
{
DispatchQueue.main.async
{
self.dataList = result
self.convertReturnsInToWantedType()
}
}
}
task.resume()
}
func convertReturnsInToWantedType()
{
// I populate finalAllItems array of dictionary object in here.
// Code might be not well-written in this scope
var datalistCount = dataList!.count
howmanyWords = datalistCount
datalistCount = datalistCount - 1
let nullLabel : String = "variable is coming null from web api"
for n in 0...datalistCount {
let oneItem = self.dataList![n]
var itemWord : String = ""
if let itemWordTemp = oneItem["itemWord"] as? String
{
itemWord = itemWordTemp
}
else
{
itemWord = nullLabel
}
var itemMeaning : String = ""
if let itemMeaningTemp = oneItem["itemMeaning"] as? String
{
itemMeaning = itemMeaningTemp
}
else
{
itemMeaning = nullLabel
}
var itemVerb2Form : String = ""
if let itemVerb2FormTemp = oneItem["itemVerb2Form"] as? String
{
itemVerb2Form = itemVerb2FormTemp
}
else
{
itemVerb2Form = nullLabel
}
var itemVerb3Form : String = ""
if let itemVerb3FormTemp = oneItem["itemVerb3Form"] as? String
{
itemVerb3Form = itemVerb3FormTemp
}
else
{
itemVerb3Form = nullLabel
}
var itemDefination : String = ""
if let itemDefinationTemp = oneItem["itemDefination"] as? String
{
itemDefination = itemDefinationTemp
}
else
{
itemDefination = nullLabel
}
var itemUsingInSentence : String = ""
if let itemUsingInSentenceTemp = oneItem["itemUsingInSentence"] as? String
{
itemUsingInSentence = itemUsingInSentenceTemp
}
else
{
itemUsingInSentence = nullLabel
}
var itemThisWordIsRelatedWithThatWord : String = ""
if let itemThisWordIsRelatedWithThatWordTemp = oneItem["itemThisWordIsRelatedWithThatWord"] as? String
{
itemThisWordIsRelatedWithThatWord = itemThisWordIsRelatedWithThatWordTemp
}
else
{
itemThisWordIsRelatedWithThatWord = nullLabel
}
var itemTrapReply1 : String = ""
if let itemTrapReply1Temp = oneItem["itemTrapReply1"] as? String
{
itemTrapReply1 = itemTrapReply1Temp
}
else
{
itemTrapReply1 = nullLabel
}
var itemTrapReply2 : String = ""
if let itemTrapReply2Temp = oneItem["itemTrapReply2"] as? String
{
itemTrapReply2 = itemTrapReply2Temp
}
else
{
itemTrapReply2 = nullLabel
}
var itemTrapReply3 : String = ""
if let itemTrapReply3Temp = oneItem["itemTrapReply3"] as? String
{
itemTrapReply3 = itemTrapReply3Temp
}
else
{
itemTrapReply3 = nullLabel
}
var itemTrapReply4 : String = ""
if let itemTrapReply4Temp = oneItem["itemTrapReply4"] as? String
{
itemTrapReply4 = itemTrapReply4Temp
}
else
{
itemTrapReply4 = nullLabel
}
finalAllItems.append(
AllItems(
itemWord:itemWord,
itemWordMeaning: itemMeaning,
itemVerb2Form: itemVerb2Form,
itemVerb3Form: itemVerb3Form,
itemDefination: itemDefination,
itemUsingInSentence: itemUsingInSentence,
itemThisWordIsReleatedWithThatWord: itemThisWordIsRelatedWithThatWord,
itemTrapReply1: itemTrapReply1,
itemTrapReply2: itemTrapReply2,
itemTrapReply3: itemTrapReply3,
itemTrapReply4: itemTrapReply4
)
)
} // FOR LOOP ENDS
} // convertReturnsInToWantedType ENDS
override var prefersStatusBarHidden: Bool {
return true
}
}
extension HomeViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//return self.dataList.count
return self.howmanyWords
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = outletForTheCollectionView.dequeueReusableCell(withReuseIdentifier: "ViewCellID", for: indexPath) as! CustomCell
cell.outletForTheViewInCell.backgroundColor = .lightGray
// word label
cell.outletForTheLabelInCell.text = self.finalAllItems[indexPath.row].itemWord
print(finalAllItems[indexPath.row].itemWord)
var allRepliesArray =
[
self.finalAllItems[indexPath.row].itemTrapReply1,
self.finalAllItems[indexPath.row].itemTrapReply2,
self.finalAllItems[indexPath.row].itemTrapReply3,
self.finalAllItems[indexPath.row].itemTrapReply4,
self.finalAllItems[indexPath.row].itemWordMeaning
]
print(allRepliesArray)
print(allRepliesArray.count)
let randomIndex1 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionA.setTitle(allRepliesArray[randomIndex1], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex1]}
print(allRepliesArray.count)
let randomIndex2 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionB.setTitle(allRepliesArray[randomIndex2], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex2]}
let randomIndex3 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionC.setTitle(allRepliesArray[randomIndex3], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex3]}
let randomIndex4 = Int(arc4random_uniform(UInt32(allRepliesArray.count)))
cell.btnOptionD.setTitle(allRepliesArray[randomIndex4], for: .normal)
allRepliesArray = allRepliesArray.filter {$0 != allRepliesArray[randomIndex4]}
cell.btnOptionE.setTitle(allRepliesArray[0], for: .normal)
cell.correctReply = self.correctAnswerArray[indexPath.row]
print("cevapDogruMu: \(cevapDogruMu)")
cell.dismiss = { [weak self] str in
//Here.
if str == "true"
{
cell.outletForTheViewInCell.backgroundColor = .green
}
else
{
cell.outletForTheViewInCell.backgroundColor = .red
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let screenSize = UIScreen.main.bounds.size
return screenSize
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let index = self.outletForTheCollectionView.contentOffset.x / self.outletForTheCollectionView.frame.size.width
self.outletForThePageController.currentPage = Int(index)
//self.outletForThePageController.numberOfPages = dataList.count
self.outletForThePageController.numberOfPages = self.howmanyWords
}
class SnappingCollectionViewLayout: UICollectionViewFlowLayout {
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) }
var offsetAdjustment = CGFloat.greatestFiniteMagnitude
let horizontalOffset = proposedContentOffset.x + collectionView.contentInset.left
let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.bounds.size.width, height: collectionView.bounds.size.height)
let layoutAttributesArray = super.layoutAttributesForElements(in: targetRect)
layoutAttributesArray?.forEach({ (layoutAttributes) in
let itemOffset = layoutAttributes.frame.origin.x
if fabsf(Float(itemOffset - horizontalOffset)) < fabsf(Float(offsetAdjustment)) {
offsetAdjustment = itemOffset - horizontalOffset
}
})
return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
}
}
} // extension ENDS
extension MutableCollection {
/// Shuffles the contents of this collection.
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
// Change `Int` in the next line to `IndexDistance` in < Swift 4.1
let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
let i = index(firstUnshuffled, offsetBy: d)
swapAt(firstUnshuffled, i)
}
}
}
extension Sequence {
/// Returns an array with the contents of this sequence, shuffled.
func shuffled() -> [Element] {
var result = Array(self)
result.shuffle()
return result
}
}
This is an example for the JSON return
[
{
"itemWord": "surpass",
"itemMeaning": "lorem",
"itemVerb2Form": "surpassVerb2",
"itemVerb3Form": "surpassVerb3",
"itemDefination": null,
"itemUsingInSentence": null,
"itemThisWordIsRelatedWithThatWord": null,
"itemTrapReply1": "lorem",
"itemTrapReply2": "lorem",
"itemTrapReply3": "lorem",
"itemTrapReply4": "lorem"
},
{
"itemWord": "affect",
"itemMeaning": "lorem",
"itemVerb2Form": "affectVerb2",
"itemVerb3Form": "affectVerb3",
"itemDefination": null,
"itemUsingInSentence": null,
"itemThisWordIsRelatedWithThatWord": null,
"itemTrapReply1": "lorem",
"itemTrapReply2": "lorem",
"itemTrapReply3": "lorem",
"itemTrapReply4": "lorem"
}
]
AllItems.swift file
import Foundation
class AllItems
{
var itemWord : String = "" // 1
var itemWordMeaning : String = "" // 2
var itemVerb2Form : String = "" // 3
var itemVerb3Form : String = "" // 4
var itemDefination : String = "Verb" // 5
var itemUsingInSentence: String = "" // 6
var itemThisWordIsReleatedWithThatWord : String = "" // 7
var itemTrapReply1 : String = ""
var itemTrapReply2 : String = ""
var itemTrapReply3 : String = ""
var itemTrapReply4 : String = ""
init(
itemWord:String,
itemWordMeaning:String,
itemVerb2Form:String,
itemVerb3Form:String,
itemDefination: String,
itemUsingInSentence:String,
itemThisWordIsReleatedWithThatWord: String,
itemTrapReply1: String,
itemTrapReply2: String,
itemTrapReply3: String,
itemTrapReply4: String)
{
self.itemWord = itemWord //1
self.itemWordMeaning = itemWordMeaning //2
self.itemVerb2Form = itemVerb2Form // 3
self.itemVerb3Form = itemVerb3Form // 4
self.itemDefination = itemDefination // 5
self.itemUsingInSentence = itemUsingInSentence // 6
self.itemThisWordIsReleatedWithThatWord = itemThisWordIsReleatedWithThatWord // 7
self.itemTrapReply1 = itemTrapReply1 // 8
self.itemTrapReply2 = itemTrapReply2 // 9
self.itemTrapReply3 = itemTrapReply3 // 10
self.itemTrapReply4 = itemTrapReply4 // 11
}
}
Data request from API is asynchronous. To solve your problem you can call the reloadData function when your finalAllItems variable is setted.
var finalAllItems = [AllItems]() {
didSet {
outletForTheCollectionView.reloadData()
}
}
I'm not sure, but I think you're not setting up the values in your cells.
Right now you're just seeing a bunch of gray cells, right? Maybe just one?
In the func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell, you should set up the values to be shown in the cells before returning them. All you're doing right now is setting up the background color, nothing else.
You should do something like cell.setUpData(finalAllItems[indexPath.row]) inside that function, and then in the cell class you have to create the setUpData method and do whatever you want to do with your data in the cell.
And yes, you should call outletForTheCollectionView.reloadData() every time you want to show new data.
at first sorry for my bad english.
My problem is that my tableview will be misrepresented as soon as I save a new file in Firebase.
When saving, a new AddViewController is called.
After saving is automatically returned to the TableviewController.
However, if I stop and restart the app so that the TableviewController is recreated, my tableview will be displayed correctly.
I create a header from an array.
Then I create the cell from another array.
I do not understand why my tableview is displayed incorrectly when I return after saving, but when I recreate the view after the app has finished everything is shown correctly.
My sample pictures:
that's right:
that's bad
My Code from TableViewController:
override func viewDidLoad() {
super.viewDidLoad()
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: #selector(TagebuchViewController.refresh), for: UIControlEvents.valueChanged)
tableView.addSubview(refresher)
loadTableview()
}
Load data from Firebase, loadTableView():
func loadTableview(){
let userID = Firebase.Auth.auth().currentUser?.uid
databaseRef = Database.database().reference().child("DiabetesIOS").child(userID!)
databaseRef.observe(.value, with: {(snapshot) in
var newItems = [Post]()
var newItemsDate = [String]()
var aNewTime = [String]()
var aNewBl = [String]()
var aNewK = [String]()
var aNewBo = [String]()
var aNewBa = [String]()
var aNewBlu = [String]()
var aNewP = [String]()
var aNewN = [String]()
var dimArrayNewTime = [[String]]()
var dimArrayNewBl = [[String]]()
var dimArrayNewK = [[String]]()
var dimArrayNewBo = [[String]]()
var dimArrayNewBa = [[String]]()
var dimArrayNewBlu = [[String]]()
var dimArrayNewP = [[String]]()
var dimArrayNewN = [[String]]()
for year in snapshot.children.allObjects as! [DataSnapshot] {
for month in year.children.allObjects as! [DataSnapshot] {
for day in month.children.allObjects as! [DataSnapshot] {
for date in day.children.allObjects as! [DataSnapshot] {
for time in date.children.allObjects as! [DataSnapshot] {
let newPost = Post(snapshot: time)
newItems.append(newPost)
let newDate = Post(snapshot: time)
newItemsDate.append(newDate.snap6Date!)
if self.snapshotCheck == 0{
self.snapshotCheckDate = newDate.snap6Date
self.snapshotCheck += 1
}
else{
}
if self.snapshotCheckDate == newDate.snap6Date{
aNewTime.append(newDate.time)
aNewBl.append(newDate.blutzucker)
aNewKe.append(newDate.ke)
aNewBo.append(newDate.bolusInsulin)
aNewBa.append(newDate.basalInsulin)
aNewBlu.append(newDate.blutdruck)
aNewP.append(newDate.puls)
aNewN.append(newDate.notiz)
}
else{
dimArrayNewTime.append(aNewTime)
dimArrayNewBl.append(aNewBlutzucker)
dimArrayNewK.append(aNewKe)
dimArrayNewBo.append(aNewBolusinsulin)
dimArrayNewBa.append(aNewBasalinsulin)
dimArrayNewBlu.append(aNewBlutdruck)
dimArrayNewP.append(aNewPuls)
dimArrayNewN.append(aNewNotiz)
aNewTime.removeAll()
aNewBl.removeAll()
aNewK.removeAll()
aNewBo.removeAll()
aNewBa.removeAll()
aNewBlu.removeAll()
aNewP.removeAll()
aNewN.removeAll()
aNewTime.append(newDate.time)
aNewBl.append(newDate.blutzucker)
aNewK.append(newDate.ke)
aNewBo.append(newDate.bolusInsulin)
aNewBa.append(newDate.basalInsulin)
aNewBlu.append(newDate.blutdruck)
aNewP.append(newDate.puls)
aNewN.append(newDate.notiz)
self.snapshotCheckDate = newDate.snap6Date
}
}
}
}
}
}
self.postArrayValue = newItems
self.aHeaderDate = newItemsDate
self.aHeaderDate = self.uniq(source: self.aHeaderDate)
dimArrayNewTime.append(aNewTime)
dimArrayNewBl.append(aNewBl)
dimArrayNewK.append(aNewK)
dimArrayNewBo.append(aNewBo)
dimArrayNewBa.append(aNewBa)
dimArrayNewBlu.append(aNewBlu)
dimArrayNewP.append(aNewP)
dimArrayNewN.append(aNewN)
self.dimArrayTime = dimArrayNewTime
self.dimArrayBl = dimArrayNewBl
self.dimArrayK = dimArrayNewK
self.dimArrayBo = dimArrayNewBo
self.dimArrayBa = dimArrayNewBa
self.dimArrayBlu = dimArrayNewBlu
self.dimArrayP = dimArrayNewP
self.dimArrayN = dimArrayNewN
newItems.removeAll()
newItemsDate.removeAll()
aNewTime.removeAll()
aNewBl.removeAll()
aNewK.removeAll()
aNewBo.removeAll()
aNewBa.removeAll()
aNewBlu.removeAll()
aNewP.removeAll()
aNewN.removeAll()
dimArrayNewTime.removeAll()
dimArrayNewBl.removeAll()
dimArrayNewK.removeAll()
dimArrayNewBo.removeAll()
dimArrayNewBa.removeAll()
dimArrayNewBlu.removeAll()
dimArrayNewP.removeAll()
dimArrayNewN.removeAll()
self.tableView.reloadData()
}){
(error) in
print(error.localizedDescription)
}
}
For my Header:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = Bundle.main.loadNibNamed("TableViewCell1", owner: self, options: nil)?.first as! TableViewCell1
headerView.date.text = aHeaderDate[section]
headerView.backgroundColor = UIColor.white
return headerView
}
NumberOfRows:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dimArrayTime[section].count
}
Number of Headers:
override func numberOfSections(in tableView: UITableView) -> Int {
return aHeaderDate.count
}
Number of Cells:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dimArrayTime[section].count
}
Section:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell2 = Bundle.main.loadNibNamed("TableViewCell2", owner: self, options: nil)?.last as! TableViewCell2
let sectionTime = dimArrayTime[indexPath.section][indexPath.row]
let sectionBl = dimArrayBl[indexPath.section][indexPath.row]
let sectionK = dimArrayK[indexPath.section][indexPath.row]
let sectionBo = dimArrayBo[indexPath.section][indexPath.row]
let sectionBa = dimArrayBa[indexPath.section][indexPath.row]
let sectionBlu = dimArrayBlu[indexPath.section][indexPath.row]
let sectionP = dimArrayP[indexPath.section][indexPath.row]
let sectionN = dimArrayN[indexPath.section][indexPath.row]
cell2.time.text = sectionTime
cell2.bl.text = sectionBl
cell2.k.text = sectionK
cell2.bo.text = sectionBo
cell2.ba.text = sectionBa
cell2.blu.text = sectionBlu
cell2.p.text = sectionP
cell2.n.text = sectionN
return cell2
}
addViewController:
#IBAction func saveInDatabaseFirebase(_ sender: Any) {
let userID = Firebase.Auth.auth().currentUser?.uid
let postRef = dataRef.child("DIOS").child(userID!).child(stringForDbYear).child(stringForDbMonth).child(stringForDbDay).child(stringForDbDate).child(stringForDbTime)
sDate = tFDate.text!
if tFBl.text == "" {
sBl = "-"
}
else{
sBl = tFBl.text!
}
if tFK.text == "" {
sK = "-"
}
else{
sK = tFK.text!
}
if tFBo.text == "" {
sBo = "-"
}
else{
sBo = tFBo.text!
}
if tFBa.text == "" {
sBa = "-"
}
else{
sBa = tFBa.text!
}
if tfBlu.text == "" {
sBlu = "-"
}
else{
sBlu = tfBlu.text!
}
if tFP.text == "" {
sP = "-"
}
else{
sP = tFP.text!
}
if tFN.text == "" {
sN = "-"
}
else{
sN = tFN.text!
}
let post = Post (date: stringForDbDate, time: stringForDbTime, day: stringForDbDay, bl: sBl, k: sK, bo: sBo, ba: sBa, blu: sBlu, p: sP, n: sN, snap1DIOS: "DIOS", snap2UserID: userID!, snap3Year: stringForDbYear, snap4Month: stringForDbMonth, snap5Day: stringForDbDay, snap6Date: stringForDbDate, snap7Time: stringForDbTime)
postRef.setValue(post.toAnyObject())
self.dismiss(animated: true, completion: nil);
}
Thank you very much for help
I am making an app for smartsearch. I have implemented through making parameters into string then append the strings.Then for search i am implementing filter to search from the search. But its getting lengthy. I want it in compact using NSPredicate.
My code is here. Can anyone make it using NSPredicate and NSCompoundPredicate
import UIKit
struct Request{
var type:String!
var firstName:String!
var lastName:String!
var combineString:String {
get {
let text = "\(self.type!) \(self.firstName) \(self.lastName)"
return text
}
}
init() {
self.type = ""
self.firstName = ""
self.lastName = ""
}
init(_ type:String,_ firstName:String,_ lastName:String) {
self.type = type
self.firstName = firstName
self.lastName = lastName
}}
class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
#IBOutlet var searchbar:UISearchBar!
#IBOutlet var headline:UILabel!
#IBOutlet var table:UITableView!
var type:Array = [String]()
var firstName:Array = [String]()
var lastName:Array = [String]()
var tempResults = Array<[Request]>()
var requestArray = Array<Request>()
var filteredArray = Array<Request>()
var isSearching = false
type = [“4343”, “45450”, “68468”, “4686”, “56461”, “48661”]
firstName = [“Tom”, “Michel”, “Steve”, “Rahul”, “Iswar”, “Kuldeep”]
lastName = [“Moody”, “Clark”, “Smith”, “Kumar”, “Pandey”, “Yadav”]
for i in 0..<requestTypeArr.count {
let type = self.type[i]
let firstName = self.firstName[i]
let lastName = self.lastName[i]
var request = Request()
request.type = type
request.firstName = firstName
request.lastName = lastName
self.requestArray.append(request)
}
let string = String(format: "Total list No %ld", self.requestArray.count)
self.headline.text = string
self.table.delegate = self
self.table.dataSource = self
self.table.contentInset = UIEdgeInsets(top: 44, left: 0, bottom: 0, right: 0)
self.table.estimatedRowHeight = 44
self.table.rowHeight = UITableViewAutomaticDimension
self.searchbar.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isSearching == true {
return self.filteredArray.count
}
return self.requestArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RquestDetailTableViewCell") as! RquestDetailTableViewCell
var request = self.requestArray[indexPath.row]
if self.isSearching == true {
request = self.filteredArray[indexPath.row]
}
cell.type.text = request.type
cell.firstName.text = request.firstName
cell.lastName.text = request.lastName
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}}
extension ViewController : UISearchBarDelegate {
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.isSearching = true
// self.table.reloadSections([0], with: .automatic)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
//Filter one
//print("Search Query:- \(searchText)")
if searchText.components(separatedBy: .whitespaces).joined(separator: "").characters.count == 0 {
if self.isSearching == true {
self.isSearching = false
self.filteredArray = Array<Request>()
self.tempResults = Array<[Request]>()
}
}else {
if self.isSearching == false {
self.isSearching = true
}
var temp = Array<Request>()
if self.tempResults.count == 0 {
temp = self.requestArray.filter({ (object) -> Bool in
//print("\nSearch Text = \(searchText.lowercased()) \nand Source Combine String = \(object.combineString.lowercased())")
let lowercaseInput = searchText.lowercased()
let lowercaseSource = object.combineString.lowercased()
let sourceComponents = lowercaseSource.components(separatedBy: .whitespaces)
let inputComponents = lowercaseInput.components(separatedBy: .whitespaces)
let sourceSet = Set(sourceComponents)
var inputSet = Set(inputComponents)
if let index = inputSet.index(of: ""){
_ = inputSet.remove(at: index)
}
var filtered = [String]()
inputSet.forEach({ (word) in
let temp = sourceSet.filter({$0.contains(word)})
//let temp2 = sourceSet.filter({$0.hasPrefix(word)})
filtered.append(contentsOf: temp)
// let temp2 = sourceSet.filter({$0.hasPrefix(word)})
//filtered.append(contentsOf: temp2)
})
let set = Set(filtered)
var isOK = set.isSubset(of: sourceSet)
if set.count == 0 {
isOK = false
}
return isOK
})
self.filteredArray = temp
}else {
if let last = self.tempResults.last {
temp = last.filter({ (object) -> Bool in
let lowercaseInput = searchText.lowercased()
let lowercaseSource = object.combineString.lowercased()
let lastInputWord = lowercaseInput.components(separatedBy: .whitespaces).last!
let sourceComponents = lowercaseSource.components(separatedBy: .whitespaces)
let inputComponents = [lastInputWord]
let sourceSet = Set(sourceComponents)
let inputSet = Set(inputComponents)
var filtered = [String]()
inputSet.forEach({ (word) in
let temp = sourceSet.filter({$0.contains(word)})
//let temp2 = sourceSet.filter({$0.hasPrefix(word)})
filtered.append(contentsOf: temp)
})
let set = Set(filtered)
var isOK = set.isSubset(of: sourceSet)
if set.count == 0 {
isOK = false
}
return isOK
})
self.filteredArray = temp
}
}
}
self.table.reloadSections([0], with: .automatic)
}
func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == " " {
self.tempResults.append(self.filteredArray)
}
if range.length == 1 {
//Handle Backspace/delete
let string = searchBar.text! as NSString
let temp = string.substring(with: range) as String
let newRange = string.range(of: temp, options: .backwards)
let newText = string.replacingCharacters(in: newRange, with: "")
let words = newText.components(separatedBy: .whitespaces).count
if words > 1 {
print("word count = \(words)")
let count = self.tempResults.count
if count > words {
self.tempResults.removeLast()
}
}else {
self.tempResults = Array<[Request]>()
}
}
return true
}
}
Tried so many times to find out what causes the fatal error. But, still can't figure it out. The first table (result table) causes this error when I try to refresh the table with pull. The second table (favoriteProductTableView) works perfect, so I didn't put any code about the second one. Wondering why. Thank you for your help.
var followArray = [String]()
var resultsNameArray = [String]()
var resultsImageFiles = [PFFile?]()
var resultsDetailsArray = [String]()
var resultsDetailsImageFiles = [PFFile?]()
var resultsObjectID = [String]()
var resultsTitle = [String]()
var personPriceArray = [String]()
var personQuantityArray = [String]()
var personOrderTypeArray = [String]()
var refresher:UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
favoriteProductTableView.hidden = true
refresher = UIRefreshControl()
refresher.tintColor = UIColor.blackColor()
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.resultsTable.addSubview(refresher)
}
override func viewDidAppear(animated: Bool) {
refreshResults()
}
func refresh(){
refreshResults()
}
func refreshResults(){
switch(segmentedControl.selectedSegmentIndex){
case 0:
followArray.removeAll(keepCapacity: false)
resultsNameArray.removeAll(keepCapacity: false)
resultsImageFiles.removeAll(keepCapacity: false)
resultsDetailsArray.removeAll(keepCapacity: false)
resultsDetailsImageFiles.removeAll(keepCapacity: false)
resultsObjectID.removeAll(keepCapacity: false)
resultsTitle.removeAll(keepCapacity: false)
personPriceArray.removeAll(keepCapacity: false)
personQuantityArray.removeAll(keepCapacity: false)
personOrderTypeArray.removeAll(keepCapacity: false)
let followQuery = PFQuery(className: "follow")
followQuery.whereKey("user", equalTo: (PFUser.currentUser()!.username)!)
followQuery.whereKey("userToFollow", notEqualTo: (PFUser.currentUser()!.username)!)
followQuery.findObjectsInBackgroundWithBlock { (objects:[PFObject]?, error: NSError?) -> Void in
if error != nil {
}
for object in objects! {
self.followArray.append(object.objectForKey("userToFollow") as! String)
}
let query = PFQuery(className: "products")
query.whereKey("userName", containedIn: self.followArray)
query.findObjectsInBackgroundWithBlock { (catchobjects:[PFObject]?, error:NSError?) -> Void in
if error != nil {
}
for catchobject in catchobjects! {
if catchobject.objectForKey("selling_price") != nil {
self.personPriceArray.append(catchobject.objectForKey("selling_price") as! String)
self.personOrderTypeArray.append("Selling")
} else {
self.personPriceArray.append(catchobject.objectForKey("buying_price") as! String)
self.personOrderTypeArray.append("Buying")
}
self.personQuantityArray.append(catchobject.objectForKey("quantity") as! String)
self.resultsNameArray.append(catchobject.objectForKey("unique_username") as! String)
self.resultsImageFiles.append(catchobject.objectForKey("profile_picture") as? PFFile)
self.resultsDetailsArray.append(catchobject.objectForKey("details") as! String)
self.resultsDetailsImageFiles.append(catchobject.objectForKey("detailsImage") as? PFFile)
self.resultsTitle.append(catchobject.objectForKey("title") as! String)
self.resultsObjectID.append(catchobject.objectId!)
}
dispatch_async(dispatch_get_main_queue()) {
self.resultsTable.reloadData()
}
self.loadEmptyLabel(self.resultsTable)
}
self.refresher.endRefreshing()
}
break
case 1:
...
break
default:
break
}
}
func loadEmptyLabel(tableView: UITableView) {
let emptyLabel = UILabel(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height))
emptyLabel.textAlignment = NSTextAlignment.Center
emptyLabel.textColor = UIColor.blackColor()
emptyLabel.text = "No matched result found."
tableView.backgroundView = emptyLabel
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
var resultCount = Int()
if tableView == resultsTable {
resultCount = resultsNameArray.count
} else {
resultCount = resultsTitleArray.count
}
if resultCount == 0 {
tableView.reloadData()
emptyLabel.hidden = false
} else {
emptyLabel.hidden = true
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numRow: Int = 0
switch(segmentedControl.selectedSegmentIndex){
case 0:
numRow = resultsNameArray.count
break
case 1:
numRow = resultsTitleArray.count
break
default:
break
}
return numRow
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == resultsTable {
let cell:favoritedTableViewCell = resultsTable.dequeueReusableCellWithIdentifier("Cell") as! favoritedTableViewCell
cell.profileLbl.text = self.resultsNameArray[indexPath.row]
cell.messageTxt.text = self.resultsDetailsArray[indexPath.row]
cell.priceLabel.text = "\(self.personOrderTypeArray[indexPath.row]) \(self.personQuantityArray[indexPath.row]) for $\(self.personPriceArray[indexPath.row])"
cell.titleLabel.text = self.resultsTitle[indexPath.row]
if resultsImageFiles[indexPath.row] != nil {
resultsImageFiles[indexPath.row]!.getDataInBackgroundWithBlock { (imageData:NSData?, error:NSError?) -> Void in
if error == nil{
let image = UIImage(data: imageData!)
cell.imgView.image = image
}
}
} else {
cell.imgView.image = UIImage(named: "Profile Picture")
}
if resultsDetailsImageFiles[indexPath.row] != nil{
resultsDetailsImageFiles[indexPath.row]?.getDataInBackgroundWithBlock({ (imageData:NSData?, error:NSError?) -> Void in
if error == nil{
let image = UIImage(data: imageData!)
cell.detailsImg.image = image
}
})
} else {
cell.detailsImg.image = UIImage(named: "Profile Picture")
}
return cell
} else {
....
}
}
Your numberOfRowsInSection function returns one of two array lengths based on segmentedControl.selectedSegmentIndex, whereas cellForRowAtIndexPath indexes the arrays based on the tableView being displayed. This doesn't look right, especially given your referencing `` which doesn't appear to be populated anywhere - should it just be resultsTitle?.
Also, you're calling self.resultsTable.reloadData() from a background thread. This is bad - it must be called from the main thread using:
dispatch_async(dispatch_get_main_queue()) {
self.resultsTable.reloadData()
}
Nevertheless, it's not clear why you've got this inside the loop either.