I've been following "iOS8 Swift Programming Cookbook"'s section on EventKit and calendars, and I've learned a lot (especially since I'm new to programming). But the next step that I want to take is populating a tableview that I have an outlet to in my ViewController with the event data so as to have a tableview list of upcoming events. Can anyone tell me how to do this?
Here's what I have so far:
import UIKit
import EventKit
import EventKitUI
class TodayViewController: UIViewController, UITableViewDataSource {
var events: AnyObject = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
requestCalendarAccess()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func requestCalendarAccess() {
let eventStore = EKEventStore()
switch EKEventStore.authorizationStatusForEntityType(EKEntityTypeEvent){
case .Authorized:
readEvents()
case .Denied:
displayAccessDenied()
case .NotDetermined:
eventStore.requestAccessToEntityType(EKEntityTypeEvent, completion:
{[weak self] (granted: Bool, error: NSError!) -> Void in
if granted{
self!.readEvents()
} else {
self!.displayAccessDenied()
}
})
case .Restricted:
displayAccessRestricted()
}
}
func displayAccessDenied(){
println("Access to the event store is denied.")
}
func displayAccessRestricted(){
println("Access to the event store is restricted.")
}
func readEvents(){
/* Instantiate the event store */
let eventStore = EKEventStore()
let icloudSource = sourceInEventStore(eventStore,
type: EKSourceTypeCalDAV,
title: "iCloud")
if icloudSource == nil{
println("You have not configured iCloud for your device.")
return
}
let calendar = calendarWithTitle("Work",
type: EKCalendarTypeCalDAV,
source: icloudSource!,
eventType: EKEntityTypeEvent)
if calendar == nil{
println("Could not find the calendar we were looking for.")
return
}
/* The event starts from today, right now */
let startDate = NSDate()
/* The end date will be 1 day from today */
let endDate = startDate.dateByAddingTimeInterval(24 * 60 * 60)
/* Create the predicate that we can later pass to the
event store in order to fetch the events */
let searchPredicate = eventStore.predicateForEventsWithStartDate(
startDate,
endDate: endDate,
calendars: [calendar!])
/* Fetch all the events that fall between
the starting and the ending dates */
let events = eventStore.eventsMatchingPredicate(searchPredicate)
as [EKEvent]
if events.count == 0 {
println("No events could be found")
} else {
// Go through all the events and print them to the console
for event in events{
println("Event title = \(event.title)")
println("Event start date = \(event.startDate)")
println("Event end date = \(event.endDate)")
}
}
}
func sourceInEventStore(
eventStore: EKEventStore,
type: EKSourceType,
title: String) -> EKSource?{
for source in eventStore.sources() as [EKSource]{
if source.sourceType.value == type.value &&
source.title.caseInsensitiveCompare(title) ==
NSComparisonResult.OrderedSame{
return source
}
}
return nil
}
func calendarWithTitle(
title: String,
type: EKCalendarType,
source: EKSource,
eventType: EKEntityType) -> EKCalendar?{
for calendar in source.calendarsForEntityType(eventType).allObjects
as [EKCalendar]{
if calendar.title.caseInsensitiveCompare(title) ==
NSComparisonResult.OrderedSame &&
calendar.type.value == type.value{
return calendar
}
}
return nil
}
func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return events.count
}
func tableView(tableView: UITableView,
cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCellWithIdentifier("cell")
as UITableViewCell
cell.textLabel!.text = /*what goes here?*/
return cell
}
Right now my events are printing to the console perfectly, but I'm not sure how to get from there to the tableview in my view controller. Any help is appreciated!
at first your event data should be accessible in you table delegate
func readEvents(){
...
let events = eventStore.eventsMatchingPredicate(searchPredicate)
as [EKEvent]
...
}
but events are NOT !!!
you fetch your data just locally in you function readEvents
eventhough you declare a store for events in your class, you never filled it
class TodayViewController: UIViewController, UITableViewDataSource {
var events: AnyObject = []
...
}
to fill the data in you class variable just remove 'redeclaration'
...
var events: [EKEvent] = []
func readEvents(){
...
events = eventStore.eventsMatchingPredicate(searchPredicate)
as [EKEvent]
...
}
The function
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell
gets passed the parameter cellForRowAtIndexPath which contains the index of the row inside your tableview. You can access that index using indexPath.row, which you should use to access your events-Array.
So for example your function could look like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
var event = self.events[indexPath.row]
cell.textLabel!.text = event.eventIdentifier
return cell
}
I don't know exactly how the EKEvent Class looks like, but Apple's Documentation of that class says there is the eventIdentifier of type String and so you can take that to test it with your tableview.
Hope you enjoy programming! :)
Related
I think my problem spans over multiple VC.
In the table VC I perform a fetch request that returns an array of Floor objects. This entity has 2 attributes (floor number and number of rooms in floors). If I assign 2 floors (0 and 1) it works and prints them. The next VC contains a picker that displays the number of floors and a text box that is used to assign the number of rooms per floor. There must be a problem with this function because it gets called only if the first item of the picker is selected (prints the result). If I have 2 floors (0 and 1 in the picker) and floor 1 is selected the function does not assign the room value to any other floor. It doesn't matter how many floors, the function will only work for the first one. I have looked of how to modify the function but did not find any suitable solutions.
The second problem is that the table view does only display one row. Lets say that for floor 0 I assign 1; than only a row with 1 appears. If anyone could help me it would mean a lot to me. Thank you
Please see the code below for the picker function:
#IBAction func setTheFloors(_ sender: UIButton) {
if storedFloors.count > 0 {
if storedFloors.first?.floorNumber == pickedFloor! {
storedFloors.first?.numberOfRooms = roomNumberValue
print("\(storedFloors.first?.floorNumber) + \(storedFloors.first?.numberOfRooms)")
}
}
do {
try managedObjectContext.save()
} catch {
fatalError("could not save context because: \(error)")
}
}
#IBAction func nextStep(_ sender: UIButton) {
}
private func loadFloorData() {
let floorRequest: NSFetchRequest<Floors> = Floors.fetchRequest()
do {
storedFloors = try managedObjectContext.fetch(floorRequest)
} catch {
print("could not load data from core \(error.localizedDescription)")
}
}
private func spinnerItems() {
for i in 0...floorValue! - 1 {
convertedFloorValues.append(String(i))
}
}
and this section of code is for the table view.
class RoomAndAlarmTypeTableVC: UITableViewController, NSFetchedResultsControllerDelegate {
//MARK: - Properties
private var managedObjectContext: NSManagedObjectContext!
private var storedFloors = [Floors]()
private var floorsAndRooms = [String: String]()
//MARK: - Actions
override func viewDidLoad() {
super.viewDidLoad()
managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
loadFloorData()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func loadFloorData() {
let floorRequest: NSFetchRequest<Floors> = Floors.fetchRequest()
do {
storedFloors = try managedObjectContext.fetch(floorRequest)
print("\(storedFloors)")
} catch {
print("could not load data from core \(error.localizedDescription)")
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return storedFloors.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let specificFloor = storedFloors[section]
return Int(specificFloor.numberOfRooms)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "house cell", for: indexPath) as! ViewRooomNumberCell
let tableSections = storedFloors[indexPath.section]
let floorItem = tableSections.numberOfRooms[indexPath.row]
let floorNumber = String(floorItem.numberOfRooms)
cell.floorNumberTxt.text = floorNumber
return cell
}
}
I am trying to populate my daily events in to tableview. I have made the connections. (datasource, delegate and tableview) But events value is returning 0.
Sorry if this has been asked else where. I need a little help.
Here is my code.
import UIKit
import EventKit
import EventKitUI
class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var eventStore: EKEventStore?
var events = [EKEvent]()
var startDate = NSDate()
var endDate = NSDate()
var cellIdentifier = "cell"
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
automaticallyAdjustsScrollViewInsets = false
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellIdentifier);
//self.tableView.reloadData()
self.eventStore = EKEventStore()
fetchEvents { (arr:[EKEvent]) in
print(arr)
self.events = arr
//reload table
}
self.tableView.reloadData()
}
func fetchEvents(completed: ([EKEvent]) -> ()) {
eventStore!.requestAccessToEntityType(EKEntityType.Event, completion: {
granted, error in
let startDt = NSDate(timeIntervalSinceNow: -24 * 60 * 60);
let predicate = self.eventStore!.predicateForEventsWithStartDate(startDt, endDate: NSDate(), calendars: nil)
let events = self.eventStore!.eventsMatchingPredicate(predicate)
completed(events)
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func onLoadListButtonClicked(sender: AnyObject)
{
self.performSegueWithIdentifier("LoadTheList", sender: nil)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
//MARK: UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//TEST PRINT EVENT COUNT
print("event count (print) \(events.count)")
return events.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "cell"
let cell:UITableViewCell! = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
let events:EKEvent! = self.events[indexPath.row]
cell.textLabel!.text = events.title
cell.detailTextLabel!.text = events.startDate.description
print("event cell returned")
return cell
}
}
Issue is your start date is NSDate(timeIntervalSinceNow: 24 * 60 * 60) that is one day ahead and your end date is current date; in short, you are checking event starts tomorrow and ends today ;)
Just use following method to get events started yesterday and ends today. For further use just change the startDt to any previous date.
func fetchEvents(completed: (NSMutableArray) -> ()) {
eventStore!.requestAccessToEntityType(EKEntityType.Event, completion: {
granted, error in
let startDt = NSDate(timeIntervalSinceNow: -24 * 60 * 60);
let predicate = self.eventStore!.predicateForEventsWithStartDate(startDt, endDate: NSDate(), calendars: nil)
let events = NSMutableArray(array: self.eventStore!.eventsMatchingPredicate(predicate))
completed(events)
})
}
Edit
Call this as:
fetchEvents { (arr:NSMutableArray) in
print(arr)
//reload your table
}
As per your comment:
I think its a breakpoint issue but I did not put a breakpoint. It's so
strange. imgur.com/a/nQGo1 imgur.com/a/MUb4i – bourbon 2 mins ago
I had looked at your code, in that remove viewWillAppear method and add self.eventStore = EKEventStore() above the fetchEvents function call in viewDidLoad.
One more important point assign arr to self.events and then reload the table. I have just changed the return type of method use following:
Method:
func fetchEvents(completed: ([EKEvent]) -> ()) {
eventStore!.requestAccessToEntityType(EKEntityType.Event, completion: {
granted, error in
let startDt = NSDate(timeIntervalSinceNow: -24 * 60 * 60);
let predicate = self.eventStore!.predicateForEventsWithStartDate(startDt, endDate: NSDate(), calendars: nil)
let events = self.eventStore!.eventsMatchingPredicate(predicate)
completed(events)
})
}
Method call:
fetchEvents { (arr:[EKEvent]) in
print(arr)
self.events = arr
//reload table
}
I hope someone can help because this is probably a simple problem, but my Parse query within a query prints the object I am looking for, but cannot append it to the array I need it in to retrieve it in a UITableView.
The error is "fatal error: index out of range" when I dequeue the results of the query in a cell.
Here's the code:
import UIKit
import Parse
import Bolts
class MessagesTableVC: UITableViewController {
var usernames = [String]()
var sentDate = [NSDate]()
var details = [String]()
var userImage = [PFFile]()
#IBAction func backToProfile(sender: AnyObject) {
self.performSegueWithIdentifier("messagesToProfile", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
let messagesQuery = PFQuery(className: "Messages")
messagesQuery.whereKey("recipientId", equalTo: PFUser.currentUser()!.objectId!)
messagesQuery.includeKey("senderId")
messagesQuery.orderByDescending("createdAt")
messagesQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error != nil {
print(error)
}
if error == nil {
if let objects = objects {
self.usernames.removeAll(keepCapacity: true)
self.sentDate.removeAll(keepCapacity: true)
self.details.removeAll(keepCapacity: true)
self.userImage.removeAll(keepCapacity: true)
for object in objects {
self.sentDate.append(object.createdAt! as NSDate)
if (object["item"] != nil) {
self.details.append(object["item"] as! String)
} else {
self.details.append(object["request"] as! String)
}
let senderObject = (object["senderId"] as! PFUser)
let senderId = (senderObject.objectId! as String)
print(senderId)
// Query for sender info
let userQuery = PFUser.query()
userQuery?.whereKey("objectId", equalTo: senderId)
userQuery?.getFirstObjectInBackgroundWithBlock({ (object, error) in
self.usernames.append((object!["username"] as! String))
//self.userImage.append(object!["profilePicture"] as! PFFile)
})
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
//self.search.resignFirstResponder()
}
}
}
})
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return sentDate.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("messageCell", forIndexPath: indexPath) as! MessageTableViewCell
//print(usernames[indexPath.row])
cell.senderUsername.text = usernames[indexPath.row]
cell.itemOrPreview.text = details[indexPath.row]
let date = sentDate[indexPath.row]
let formatter = NSDateFormatter()
formatter.dateStyle = NSDateFormatterStyle.LongStyle
formatter.timeStyle = .ShortStyle
let dateString = formatter.stringFromDate(date)
cell.sentDate.text = dateString
//userImage[indexPath.row].getDataInBackgroundWithBlock { (data, error) in
// if let downloadedItemImage = UIImage(data: data!) {
// cell.senderImage?.image = downloadedItemImage
//}
//}
return cell
}
override func viewWillAppear(animated: Bool) {
tableView.reloadData()
}
}
As I may guess, you might get inconsistent number of elements in sentDate and usernames because you append to usernames via asynchronous getFirstObjectInBackgroundWithBlock method, so, by the time you call reloadData on tableView, all user names might not be yet added to usernames. You might have less items in usernames then in sentDate by the time your tableView callback fires and in numberOfItems you return number of items in sentDate.
In order to fix that you need at first refactor your code, it has a lot of places things might go wrong. I won't give any specific advise, but, seems, you might want to wait before you get all the data before you reload your tableView.
I have a recordtype - "DiningTypes". "DiningTypes only has one field type, which is a string. I have 5 records... and it takes 3-4 second to load a table. How is that this is so slow? Do I need to begin the fetching process in a previous controller to have quicker UI response times?
import UIKit
import CloudKit
class table1: UITableViewController {
var categories: Array<CKRecord> = []
var fetchedcategories: Array<CKRecord> = []
override func viewDidLoad() {
super.viewDidLoad()
func fetchdiningtypes()
{
let container = CKContainer.defaultContainer()
let publicDatabase = container.publicCloudDatabase
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "DiningTypes", predicate: predicate)
publicDatabase.performQuery(query, inZoneWithID: nil) { (results, error) -> Void in
if (error != nil)
{
print("Error" + (error?.localizedDescription)!)
}
else
{
for result in results!
{
self.categories.append(result)
}
}
}
}
fetchdiningtypes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return categories.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("dining") as! table1cell
let restaurant: CKRecord = categories[indexPath.row]
cell.Name.text = restaurant.valueForKey("Name") as? String
return cell
}
}
The default quality of service for CloudKit operations is NSQualityOfServiceUtility. If your application isn't in the foreground when the request runs you may see operations take longer than usual to run.
Try using CKQueryOperation and setting its qualityOfService to NSOperationQualityOfServiceUserInitiated.
I have a UIViewController with a UITableView.
At the top I have a UISegmentedController and then a UITableView.
I want the rows to be sorted when you press the segmented controls. Everything is working fine, the rows get displayed properly, but when I press the segmented control button, I call a method that sorts the array that has been displayed in the table view, but they don't get refreshed in the view unless I don't scroll to the bottom and to the top. I call the method tableView.reloadData() after sorting this array, but it doesn't update the tableview.
Here is my code:
import UIKit
import EventKit
extension RangeReplaceableCollectionType where Generator.Element : Equatable {
mutating func removeObject(object : Generator.Element) {
if let index = self.indexOf(object) {
self.removeAtIndex(index)
}
}
}
class EventsViewController: UIViewController {
var calendarName:String!
var currentStat = Stat()
var eventStore = EKEventStore() //represents the Calendar database. Point of contact for accessing calendar
var icloudEventSource: EKSource? //represents the account that a calendar belongs to.
var startDate=NSDate().dateByAddingTimeInterval(-31556926)
var endDate=NSDate().dateByAddingTimeInterval(31556926)
var yourCalendar: EKCalendar?
var calendar: EKCalendar? //represents a calendar in Event Kit
var numberOfCalendars : Int = 0
var calendarsArray = NSMutableArray()
var calendarsPrueba : [EKCalendar]?
var calendarioSeleccionado:String!
var delegate: passDataBackDelegate?
var events : [EKEvent]!
var tableView : UITableView?
var selectedMarks = [StatEvents]()
var selectedIndex = [NSIndexPath]()
var orderedStatEvents = [StatEvents]()
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var textLabel: UILabel!
#IBAction func indexChanged(sender: UISegmentedControl) {
switch segmentedControl.selectedSegmentIndex {
case 0:
orderTable(0)
case 1:
orderTable(1)
default:
break;
}
}
func orderTable(order: Int) {
switch order {
case 0:
currentStat.statEvents.sortInPlace({ $0.name.compare($1.name) == NSComparisonResult.OrderedAscending })
case 1:
currentStat.statEvents.sortInPlace({ $0.name.compare($1.name) == NSComparisonResult.OrderedDescending })
default:
break;
}
tableView?.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
eventStore.requestAccessToEntityType(EKEntityType.Event,
completion: {(granted: Bool, error:NSError?) in
if !granted {
print("Access to store not granted")
}
})
// Buscamos la cuenta de iCloud que contiene los calendarios
for source in eventStore.sources{
if source.sourceType.rawValue == EKSourceType.CalDAV.rawValue && source.title.lowercaseString == "icloud"{
icloudEventSource = source
}
}
///////Mostramos solo calendarios de iCloud//////
if (icloudEventSource != nil){
let calendars = icloudEventSource!.calendarsForEntityType(EKEntityType.Event)
print("1 The iCloud event source was found = \(icloudEventSource!.title)")
print("1 Number of calendars = \(calendars.count)")
for calendars in calendars{
yourCalendar = (calendars as EKCalendar)
print(yourCalendar!.title)
calendarsArray.addObject(yourCalendar!.title)
}
}else{
print("Could not find the iCloud event source")
}
//////Mostramos todos los calendarios///////
let calendars = eventStore.calendarsForEntityType(EKEntityType.Event) //Devuelve los calendarios que son eventos
numberOfCalendars = calendars.count
print("Number of calendars = \(calendars.count)")
for calendars in calendars as [EKCalendar] {
print("events = \(calendars.title)")
calendarsArray.addObject(calendars.title)
}
func calendarEventsWithName( name:String ) -> [EKCalendar]? {
let calendars = eventStore.calendarsForEntityType(EKEntityType.Event) as [EKCalendar]
for cal in calendars {
if cal.title == name {
return [cal]
}
}
print ("failed to find calendar")
return nil
}
let predicate = eventStore.predicateForEventsWithStartDate(startDate, endDate: endDate, calendars: calendarEventsWithName(currentStat.statCalendar))
print("startDate:\(startDate) endDate:\(endDate)")
events = eventStore.eventsMatchingPredicate(predicate) as [EKEvent]!
let calendar = NSCalendar.currentCalendar()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy" //format style. Browse online to get a format that fits your needs.
if events != nil {
print(events.count)
for i in events {
let components = calendar.components(.Hour, fromDate: i.startDate, toDate: i.endDate, options: [])
currentStat.statEvents.append(StatEvents(name: i.title, dateRanges: [i.startDate, i.endDate], hours: components.hour))
}
} else {
print("No hay eventos en este calendario")
}
}
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return events.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
tableView.allowsMultipleSelection = true
cell.textLabel?.font = UIFont.systemFontOfSize(8.0)
cell.textLabel?.text = "\(currentStat.statEvents[indexPath.row].name) \(currentStat.statEvents[indexPath.row].dateRanges) horas=\(currentStat.statEvents[indexPath.row].hours)"
if let selectedPaths = tableView.indexPathsForSelectedRows {
let selected = selectedPaths.filter(){ $0 == indexPath }
if selected.count > 0 {
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (selectedMarks.contains(currentStat.statEvents[indexPath.row])){
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
}
print("borro")
selectedMarks.removeObject(currentStat.statEvents[indexPath.row])
} else {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .Checkmark
}
print("añado")
selectedMarks.append(currentStat.statEvents[indexPath.row]) //add the object to selectedMarks
}
selectedIndex = tableView.indexPathsForSelectedRows!
tableView.reloadData()
}
#IBAction func done(sender: AnyObject) {
selectedMarks.sortInPlace({ $0.dateRanges[0].compare($1.dateRanges[0]) == NSComparisonResult.OrderedAscending })
currentStat.statEvents = selectedMarks
navigationController!.popViewControllerAnimated(true)
}
}
The only way how I can imagine it is happening — tableView is nil in a orderTable call.
I can not find anywhere in the code assignment of table to a tableView. How is it initialized? It also worth to mention that tableView in delegate and dataSource methods a local parameter of methods, not an instance variable.
Mark it as IBOutlet and set it in IB as you do with textLabel and segmentedControl or you can change UIViewController to UITableViewController and update IB as well.