Unresolved Identifier for Table (Swift 2) - ios

I was trying to make a table show dates from a calendar in the cells but when I wrote the array it gave me the error of 'Unresolved Identifier for "Date"'
Here is the code:
import UIKit
class DatesTableViewController: UITableViewController {
// MARK: Properties
var dates = [Date]()
override func viewDidLoad() {
super.viewDidLoad()
func loadSampleDates() {
let date1 = Date(print(CALENDAR_CLOCK))!
let date2 = Date(print(CALENDAR_CLOCK))!
let date3 = Date(print(CALENDAR_CLOCK))!
let date4 = Date(print(CALENDAR_CLOCK))!
dates += [date1, date2, date3, date4]
}
The file is in the correct group, it is pointing to an existing table and cell, I am just unsure what else to check for.
I will preface this by saying I am newer to Swift so I might just be simply missing an obvious mistake, but based on the iOS Developer site this seems to be the correct way to write this code.

Date is an unresolved identifier (unless it's a separate class you wrote yourself) — you probably want to use NSDate:
import UIKit
class DatesTableViewController: UITableViewController {
// MARK: Properties
dynamic var dates = [NSDate]()
override func viewDidLoad() {
super.viewDidLoad()
func loadSampleDates() {
let date1 = NSDate(print(CALENDAR_CLOCK))
let date2 = NSDate(print(CALENDAR_CLOCK))
let date3 = NSDate(print(CALENDAR_CLOCK))
let date4 = NSDate(print(CALENDAR_CLOCK))
dates += [date1, date2, date3, date4]
}
}}
Note that the NSDate print function will always return a result — it's not optional, so there's no need to use an ! to force-unwrap it.

Related

How to change the backgroungColor cell in tableView with timeInterval using Swift

I'm trying to change the cell backgroungColor after 3.5 month. I have a textField where i put the date and after 3.5 month of that date I want to change the color of the cell in red.
I tried this where date1 is the date from textField and date2 is this from (isToday) where i have put 106 day = 3.5 month
let isToday= Date.now.addingTimeInterval(106)
func isSameDay(date1: Date, date2: Date) -> Bool {
let diff = Calendar.current.dateComponents([.day], from: date1, to: date2)
if diff.day == 0 {
return true
}
else {
return false
}
}
Inside cellForRowAt i have used like this
var documentSendDate = "05.08.2022"// this is example to be more understandable
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM/dd/yyyy"
let date = dateFormatter.date(from: documentSendDate)
if date != nil {
let isDayToday = isSameDay(date1: date!, date2: isToday) // here I call the function above
if isDayToday == true {
if customer.isToday == true {
cell.backgroundColor = .red
}
}
}
But I have this checkBox and when I check it or uncheck it change the color of the random cells. Can someone help me with this please?
Here is how i wanted to look.
UITableView is a recycle-list view, so it will reuse the cell UI instance to display data for the corresponding indexPath.
First, modify your code to add a new way of dateFormatter declaration.
// Use lazy var to reduce initialization cost
// Because initializing a new DateFormatter is not cheap, it can consume CPU time like initializing a new NumberFormatter
// lazy var will be only initialized once on the first call/use
lazy var dateFormatter = DateFormatter()
func viewDidLoad() {
super.viewDidLoad()
dateFormatter.dateFormat = "MMM/dd/yyyy"
}
It is a reusable UI, so UI won't hold the data or state. The cellForRowAt will be called multiple times when you scroll tableView or when tableView needs to re-layout,... to display the corresponding data-state for each indexPath.
That is why you must not initialize or do some big calculations/long waiting here. It will freeze/delay your UI (ref: DispatchQueue.main or MainQueue).
So inside your cellForRowAt function, you need to add logic for all cases if you use switch/if-else.
var documentSendDate = "05.08.2022"// this is example to be more understandable
// Here I combine all checks into one if-else
// Order of check is left-to-right.
// It is condition1 AND condition2 AND condition3 (swift syntax)
if let date = dateFormatter.date(from: documentSendDate),
let isDayToday = isSameDay(date1: date!, date2: isToday),
customer.isToday == true {
cell.backgroundColor = .red
} else {
cell.backgroundColor = .clear // or your desired color
}

How to load JSON Data into FSCalendar Swift 5

I am trying to load my JSON Data into FSCalendar.
I understand from the documentation that when you use an array that can be show in the calendar with the dots. I am wanting to do that same thing but instead to have the dots appear from my dates listed in my JSON file. I have loaded the JSON file into my bundle as well as made a function to load the JSON data and I have created a structure.
My problem comes in when I am trying to use an array from the structure and then load that array into the "func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {" function. I have been working on this for a while and could use some help. Thanks
JSON Data: - I titled the JSON file data.json
[
{
"event": "Christmas",
"date": [
"2021-01-02",
"2021-01-03",
"2021-01-04"
]
}
]
View Controller:
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
}
Data Model:
struct EventsData: Codable {
var event: String
var date: [String]
}
JSON loader:
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)
}
}
}
}
EDIT:
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
}
Check if you have this in your code:
// FSCalendarDataSource
func calendar(calendar: FSCalendar!, hasEventForDate date: NSDate!) -> Bool {
return shouldShowEventDot
}
Just convert your string date into Date with DateFormatter and then just go through your array and check if the date (from the calendar function) matches any of your dates in the event.
You have a number of problems.
First, you are trying to use SwiftUI constructs (#Published) in a Swift app. That won't work.
Second, you have your dates coming in as an array of strings. I suggest setting up your Codable protocol conformance using a custom Date decoding stategy.
This link shows how to set up your JSONDecoder to use a custom date decoding strategy that takes a custom DateFormatter.
Next, you need some way to update your UI when new data is read from your JSON input. SwiftUI has built-in mechanisms for automatically responding to state changes, but you're not using SwiftUI, so those don't apply.
You have a DataLoader class that loads JSON data. It currently reads hard-coded JSON from a file, synchronously. I assume that you want to load the data from the internet, which would be async. Thus your approach won't work.
I suggest you set up your DataLoader class to either have a delegate that it notifies when it has completed loading new data, or set it up to take requests with a completion handler.
If you don't know how to do either of those things then you need to stop and learn some fundamentals. Read up on Swift async networking, completion handlers, and the delegate design pattern before you continue.

PrepareForSegue for dynamic Array in UITableView

I want to make programmatically segue from TableView. Content of the cells is dynamic - the're changing, so I can't wrap segue to the number of row (ex. indexPath.row = 1). My array is like that:
myArray = [value1, value2, value3]
But value1 can be today "A", but tomorrow will be "B". So today value1 should redirect to AController, but tomorrow - to BController. Name of the value is of course displayed in the TableView.
I suppose prepareForSegue should be based on name of the value (ex. if name of the value is 'A', then...). But I don't know the method.
Any help will be appreciated :)
To be more clear - how my array is generated:
let cal = NSCalendar.currentCalendar()
let fmt = NSDateFormatter()
var countDays = [String]()
override func viewDidLoad() {
super.viewDidLoad()
fmt.dateFormat = "EEEE"
fmt.locale = NSLocale(localeIdentifier: "pl_PL")
var date = cal.startOfDayForDate(NSDate())
while countDays.count < 7 {
let weekDay = cal.component(.Weekday, fromDate: date)
if weekDay != 0 {
countDays.append(fmt.stringFromDate(date))
}
date = cal.dateByAddingUnit(.Day, value: 1, toDate: date, options: NSCalendarOptions(rawValue: 0))!
}
print(countDays)
You can use "didselectRowAtIndex" delegate method of tableview. You will get the current index path of cell which user has selected/clicked.Use this index path to retrieve corresponding object in your array.Next check the value in retrieved object "A" or "B" using if/else, depending on this you can launch your "AController" or "Controller".Use prepare for segue to launch you specific controller.
Note : all this logic should be done in you "didselectRowAtIndex" method.
Hope this helps.
Ok, I solved this with code:
let cell: UITableViewCell =
tableView.cellForRowAtIndexPath(indexPath)!
let str: String = cell.textLabel!.text!
if str.containsString("A") {
performSegueWithIdentifier("AMonday", sender:self)
}
Easy, but finding this was painful ;)

How to output dates from an array in Swift?

Im making a simple planner app which sends notifications to users at specific times that events occur.
I have set up a table to store the data and I am storing individual values inside of an array.
I am encountering a problem outputting the NSDates that I have stored inside of my array.
import UIKit
extension NSDate {
convenience init(dateString:String, format:String="h-mm a") {
let formatter = NSDateFormatter()
formatter.timeZone = NSTimeZone.defaultTimeZone()
formatter.dateFormat = format
let d = formatter.dateFromString(dateString)
self.init(timeInterval:0, sinceDate:d!)
}
class MedicineTableViewController: UITableViewController {
//MARK Properties
var medicines = [Medicine]()
override func viewDidLoad() {
super.viewDidLoad()
loadSampleMedicine()
}
func loadSampleMedicine() {
let medicine1 = Medicine(name: "Inhaler", time1: NSDate(dateString: "08:00 a"), time2: NSDate(dateString: "10:00 a"), time3: NSDate(dateString: "02:00 p"), time4: NSDate(dateString: "06:00 p"), time5: NSDate(dateString: "10:00 p"))
medicines.append(medicine1!)
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return medicines.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "MedicineTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MedicineTableViewCell
let medicine = medicines[indexPath.row]
cell.nameLabel.text = medicine.name
cell.takeAt.text = "Take At:"
cell.time1Label.text = medicine.time1
cell.time2Label.text = medicine.time2
cell.time3Label.text = medicine.time3
cell.time4Label.text = medicine.time4
cell.time5Label.text = medicine.time5
return cell
}
This returns the error "Cannot assign a value of 'NSDate' to a value of type String?"
Is there a way to convert these NSDates into strings?
I have come up with some other possible solution but it involves reworking the whole application so I'd prefer to avoid them if possible.
My possible solution is to rework the data that the user inputs to be a pickerView which has 3 columns one cycling the numbers 01 through to 12, the second 00 to 59 and the third am and pm. and then take the overall string produced and store it in the array. This would allow me to easily print it out since it is just a stored string. Then when I come to the stage at which I am making the notification system I could use the "dateString" function to convert from strings to dates and then program my notifications from that.
So overall I would like to know if I'm able to just print out the NSDates stored in my array or if not if my possible solution would work?
Thanks.
You can use NSDateFormatter. There is a function called stringFromDate. Here is an example.
var date = NSDate() //Or whatever your date is
var stringDate = NSDateFormatter().stringFromDate(date)

How do I return the results of this function?

How can I return steps from this HealthKit Query?
I get error: Missing argument for parameter #1 in call. Code:
import UIKit
import HealthKit
class ViewController: UIViewController {
var steps = Double()
var date = NSDate()
var query = performHKQuery() -->error: Missing argument for parameter #1 in call
override func viewDidLoad() {
super.viewDidLoad()
performHKQuery()
printsteps()
}
func performHKQuery () -> (steps: Double, date: NSDate){
let healthKitManager = HealthKitManager.sharedInstance
let stepsSample = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)
let stepsUnit = HKUnit.countUnit()
let sampleQuery = HKSampleQuery(
sampleType: stepsSample,
predicate: nil,
limit: 0,
sortDescriptors: nil)
{
(sampleQuery, samples, error) in
for sample in samples as [HKQuantitySample]
{
self.steps = sample.quantity.doubleValueForUnit(stepsUnit)
self.date = sample.startDate
}
}
healthKitManager.healthStore.executeQuery(sampleQuery)
return (steps, date)
}
func printsteps() {
println(query.steps) -->error: ViewController does not have a member named query
}
Any help would be much appreciated! If you can also please explain why your solution works then that would be great! Thanks
Code has been updated after feedback from #jrturton
HKQuery is the name of a class, and you're using it as a variable name. This is confusing the compiler.
Change the name to query or something instead.
You also have some structural problems:
class ViewController: UIViewController {
var steps = Double()
var date = NSDate()
var HKQuery = performHKQuery() -->error: Missing argument for parameter #1 in call
Here you're declaring a property and initialising it straight away. You can't use this as an initializer since self, that owns the method, doesn't exist at initialization.
Change the declaration to:
var query : (steps: Double,date: NSDate)?
This sets it as an optional tuple type. In viewDidLoad, you do this:
query = performHKQuery()
To set the value.
Then, in printSteps, do this:
func printsteps() {
println(query?.steps)
}

Resources