enter code hereI'm trying to add a calendar feature to my app, but I'm having 2 errors on two different viewcontrollers, I can't find out what I am missing.
The error says:
Value of type AddEventViewController has no member "Calendar" on the line addEventVC.calendar = calendar
2nd viewcontroller
1st viewcontroller
Code:
import UIKit
import EventKit
class EventsViewController: UIViewController, UITableViewDataSource, EventAddedDelegate {
#IBOutlet weak var tableView: UITableView!
var calendar: EKCalendar!
var events: [EKEvent]?
#IBOutlet weak var eventsTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
loadEvents()
}
func loadEvents() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let startDate = dateFormatter.date(from: "2016-01-01")
let endDate = dateFormatter.date(from: "2016-12-31")
if let startDate = startDate, let endDate = endDate {
let eventStore = EKEventStore()
let eventsPredicate = eventStore.predicateForEvents(withStart: startDate, end: endDate, calendars: [calendar])
self.events = eventStore.events(matching: eventsPredicate).sorted {
(e1: EKEvent, e2: EKEvent) in
return e1.startDate.compare(e2.startDate) == ComparisonResult.orderedAscending
}
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let events = events {
return events.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "basicCell")!
cell.textLabel?.text = events?[(indexPath as NSIndexPath).row].title
cell.detailTextLabel?.text = formatDate(events?[(indexPath as NSIndexPath).row].startDate)
return cell
}
func formatDate(_ date: Date?) -> String {
if let date = date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy"
return dateFormatter.string(from: date)
}
return ""
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! UINavigationController
let addEventVC = destinationVC.childViewControllers[0] as! AddEventViewController
addEventVC.calendar = calendar
addEventVC.delegate = self
}
// MARK: Event Added Delegate
func eventDidAdd() {
self.loadEvents()
self.eventsTableView.reloadData()
}
}
AddEventViewController :
class AddEventViewController: UIViewController {
#IBOutlet weak var eventNameTextField: UITextField!
#IBOutlet weak var eventStartDatePicker: UIDatePicker!
#IBOutlet weak var eventEndDatePicker: UIDatePicker!
var delegate: EventAddedDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.eventStartDatePicker.setDate(initialDatePickerValue(), animated: false)
self.eventEndDatePicker.setDate(initialDatePickerValue(), animated: false)
}
func initialDatePickerValue() -> Date {
let calendarUnitFlags: NSCalendar.Unit = [.year, .month, .day, .hour, .minute, .second]
var dateComponents = (Calendar.current as NSCalendar).components(calendarUnitFlags, from: Date())
dateComponents.hour = 0
dateComponents.minute = 0
dateComponents.second = 0
return Calendar.current.date(from: dateComponents)!
}
#IBAction func cancelButtonTapped(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
#IBAction func addEventButtonTapped(_ sender: UIButton) {
// Create an Event Store instance
let eventStore = EKEventStore();
// Use Event Store to create a new calendar instance
if let calendarForEvent = eventStore.calendar(withIdentifier: self.calendar.calendarIdentifier)
{
let newEvent = EKEvent(eventStore: eventStore)
newEvent.calendar = calendarForEvent
newEvent.title = self.eventNameTextField.text ?? "Some Event Name"
newEvent.startDate = self.eventStartDatePicker.date
newEvent.endDate = self.eventEndDatePicker.date
// Save the event using the Event Store instance
do {
try eventStore.save(newEvent, span: .thisEvent, commit: true)
delegate?.eventDidAdd()
self.dismiss(animated: true, completion: nil)
} catch {
let alert = UIAlertController(title: "Event could not save", message: (error as NSError).localizedDescription, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(OKAction)
self.present(alert, animated: true, completion: nil)
}
}
}
}
You are calling addEventVC.calendar = calendar but your AddEventViewController doesn't have a variable called calendar which is why you get the error AddEventViewController has no member "Calendar".
Related
Hi all,
I am trying to build an app for my school project that I am building on Xcode for iOS. The app involves the user being able to save information about their bills. This data is string data and includes the potential for the user being able to save the name of a bill and when the bill was received. I want it that if the bill is related to a specific expenses, for that data to be saved to a specific record that holds data for that specific expense. For example, if the user received a bill for their car, they would enter the bill details and that data could be saved to one specific record that holds all car expense bill data. The way the user could specify where they want to data to go too is through switching on the relevant switch. I am not sure how I can get it that when the user turns on, for example car, that the data will save to that record. Could you please help?
I have included my code and the photo of my interface.
Thank you
class ViewControllerAdd: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cars.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//ensure the cell identifier has been labelled "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let cars = cars[indexPath.row];
let text = "\(cars.provider) \(cars.date)";
cell.textLabel?.text=text
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
tblCar.delegate = self
tblCar.dataSource = self
tblCar.reloadData()
// Formatting for take picture button
imgView.backgroundColor = .secondarySystemBackground
btnLook.backgroundColor = .systemBlue
btnLook.setTitle("Take Picture", for: .normal)
btnLook.setTitleColor(.white, for: .normal)
// datepicker function from https://www.youtube.com/watch?v=fhRJ5HQjBIE
// This is how the date picker changes the date and date is saved
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
datePicker.addTarget(self, action: #selector(dateChange(datePicker:)), for: UIControl.Event.valueChanged)
datePicker.frame.size = CGSize(width: 0, height: 300)
datePicker.preferredDatePickerStyle = .wheels
txtDate.inputView = datePicker
txtDate.text = formateDate(date: Date())
// Getting keyboard to retract
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
//outlet
// Make segmented control action
#IBOutlet weak var txtBill: UITextField!
#IBOutlet weak var txtDate: UITextField!
#IBOutlet weak var btnLook: UIButton!
#IBOutlet weak var swiCar: UISwitch!
#IBOutlet weak var imgView: UIImageView!
#IBOutlet weak var tblCar: UITableView!
struct Car{
let provider: String
let date: String
// let bill: String
}
struct Went{
let provider: String
let date: String
// let bill: String
}
struct South{
let provider: String
let date: String
// let bill: String
}
struct Bruns{
let provider: String
let date: String
// let bill: String
}
struct Home{
let provider: String
let date: String
// let bill: String
}
struct Telephone{
let provider: String
let date: String
// let bill: String
}
var cars: [Car] = []
var went: [Went] = []
var south: [South] = []
var bruns: [Bruns] = []
var home: [Home] = []
var telephone: [Telephone] = []
//action
#IBAction func btnAdd(_ sender: Any) {
let newCar = Car(provider: txtBill.text!, date:txtDate.text!)
let newWent = Went(provider: txtBill.text!, date: txtDate.text!)
let newBruns = Bruns(provider: txtBill.text!, date: txtDate.text!)
let newSouth = South(provider: txtBill.text!, date: txtDate.text!)
let newHome = Home(provider: txtBill.text!, date: txtDate.text!)
let newTelephone = Telephone(provider: txtBill.text!, date: txtDate.text!)
cars.append(newCar)
went.append(newWent)
south.append(newSouth)
bruns.append(newBruns)
home.append(newHome)
telephone.append(newTelephone)
let imageData = imgView.image!.pngData()
let compressedImage = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(compressedImage!, nil, nil, nil)
let alert = UIAlertController(title: "Saved", message: "Image Saved", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style:.default, handler: nil)
alert.addAction(okAction)
self.present(alert, animated: true, completion:nil)
if swiCar.isOn{
cars.append(newCar) = tblCar
}
}
// Functionality
#IBAction func btnPhoto(_ sender: Any) {
// Checks if app can access camera
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
// If camera can be accessed, it will set the class to the delegate and control the camera
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerController.SourceType.camera
// Allows user to edit photo
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
}
#objc func dateChange(datePicker: UIDatePicker) {
txtDate.text = formateDate(date: datePicker.date)
}
func formateDate(date: Date) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "MMMM dd yyyy"
return formatter.string(from: date)
}
}
If you want to segregate expenses based on type of expenses, have enum of "expenseType" something like below.
enum ExpenseType{
case Car
case Telephone
case Grossary
case Misc
}
Have a single expense object in which mention "expenseType" as attribute. Based on user selection of switch add that expense to corresponding record.
In this case you should not allow user to select more than one switch.
I'm trying do delete the note from Realm in my NotesApp and facing this error: "Can only delete an object from the Realm it belongs to". This note has been saved before also in Realm and
could display it in my TableView by tapping on the date in my FSCalendar. I tried to replace realm.add(item) with realm.create(item), but also got the error: "Cannot convert value of type 'T' to expected argument type 'Object.Type' (aka 'RealmSwiftObject.Type')". I'm new in programming, so any help would be appreciated. Here's the relevant code code:
in my ToDoListItem.swift
class ToDoListItem: Object {
#objc dynamic var noteName: String = ""
#objc dynamic var date: Date = Date()
#objc dynamic var descriptionText: String = ""
#objc dynamic var noteImage = Data()
init(date: Date, noteName: String) {
self.date = date
self.noteName = noteName
}
override init() {
self.noteName = ""
self.date = Date()
self.descriptionText = ""
self.noteImage = Data()
}
}
in my RealmManager.swift
class RealmManager {
static let shared = RealmManager()
private let realm = try! Realm()
func write<T: Object>(item: T) {
realm.beginWrite()
realm.add(item)
try! realm.commitWrite()
}
func getObjects<T: Object>(type: T.Type) -> [T] {
return realm.objects(T.self).map({ $0 })
}
func delete<T: Object>(item: T) {
try! realm.write {
realm.delete(item)
}
}
}
in my ViewController where i can edit and delete the notes
#IBAction func didTapDelete() {
let note = ToDoListItem()
RealmManager.shared.delete(item: note)
self.deletionHandler?()
navigationController?.popToRootViewController(animated: true)
}
and finally in my TableViewController where the notes are displayed (honestly i think the problem is hidden here but cannot find it...
#IBOutlet var tableViewPlanner: UITableView!
#IBOutlet var calendarView: FSCalendar!
private var data = [ToDoListItem]()
var datesOfEvents: [String] {
return self.data.map { DateFormatters.stringFromDatestamp(datestamp: Int($0.date.timeIntervalSince1970)) }
}
var items: [ToDoListItem] = []
func getCount(for Date: String) -> Int {
var count: [String : Int] = [:]
for date in datesOfEvents {
count[date] = (count[date] ?? 0) + 1
}
return count[Date] ?? 0
}
func getEventsForDate(date: Date) -> [ToDoListItem] {
let string = DateFormatters.stringFromDatestamp(datestamp: Int(date.timeIntervalSince1970))
return self.data.filter {DateFormatters.stringFromDatestamp(datestamp: Int($0.date.timeIntervalSince1970)) == string }.sorted(by: {$0.date < $1.date})
}
override func viewDidLoad() {
super.viewDidLoad()
calendarView.rounding()
tableViewPlanner.rounding()
data = RealmManager.shared.getObjects(type: ToDoListItem.self)
self.items = self.getEventsForDate(date: Date())
calendarView.delegate = self
calendarView.dataSource = self
tableViewPlanner.delegate = self
tableViewPlanner.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.calendarView.select(Date())
self.calendarView.reloadData()
refresh()
}
//MARK:- TableView Data Source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count //data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: K.plannerCellIdentifier, for: indexPath) as! NoteTableViewCell
let note = self.items[indexPath.row]
cell.configureCell(note: note)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let note = data[indexPath.row]
guard
let vc = storyboard?.instantiateViewController(identifier: K.infoVCIdentifier) as? InfoViewController else { return }
vc.note = note
vc.deletionHandler = { [weak self] in
self?.refresh()
}
vc.title = note.noteName
navigationController?.pushViewController(vc, animated: true)
}
//MARK:- User Interaction
#IBAction func didTapAddButton() {
guard
let vc = storyboard?.instantiateViewController(identifier: K.entryVCIdentifier) as? EntryViewController else { return }
vc.completionHandler = { [weak self] in
self?.refresh()
}
vc.title = K.entryVCTitle
navigationController?.pushViewController(vc, animated: true)
}
func refresh() {
DispatchQueue.main.async {
self.data = RealmManager.shared.getObjects(type: ToDoListItem.self)
self.tableViewPlanner.reloadData()
self.calendarView.reloadData()
}
}
}
extension PlannerViewController: FSCalendarDelegateAppearance & FSCalendarDataSource {
func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, eventDefaultColorsFor date: Date) -> [UIColor]? {
let dateString = DateFormatters.yearAndMonthAndDateFormatter.string(from: date)
if self.datesOfEvents.contains(dateString) {
return [UIColor.blue]
}
return [UIColor.white]
}
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
self.items = self.getEventsForDate(date: date)
self.tableViewPlanner.reloadData()
}
func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
let dateString = DateFormatters.yearAndMonthAndDateFormatter.string(from: date)
let count = self.getCount(for: dateString)
self.tableViewPlanner.reloadData()
return count
}
}
The real problem is the didTapDelete function -- Why are you creating a new note just to delete it (I hope it was only to test out realm delete syntax). You should delete the note object that you passed to the view controller to edit / delete. (vc.note in did select row -> self.note in the other VC - where didTapDelete is)
So your did tap delete will look like --
RealmManager.shared.delete(item: note)
//show deleted alert & go back
A little explanation on the error - Just instantiating a Realm object (ToDoListItem()) does not add it to Realm (the Database system). To delete / edit a realm object, it has to be either fetched from a realm (RealmManager.shared.getObjects(type: ToDoListItem.self)) or added to the realm.
I'd advise going through a Realm tutorial before jumping in the code (there are plenty of them)
I'm working in a chat application. Saving sender and receiver messages to firebase. My issue when tried to load array message to TableView, messages are not completely loaded. it shows gap for remaining messages.
MainChatViewController.swift
var messages = [Message]()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("message count::\(messages.count)")
let message = messages[indexPath.row]
if let cell = chatTableView.dequeueReusableCell(withIdentifier: "Message") as? mainChatScreenTableViewCell {
cell.tag = indexPath.row
cell.configCell(message: message)
return cell
} else {
return mainChatScreenTableViewCell()
}
}
func loadData() {
Database.database().reference().child("messages").child(messageId)
.observe(.value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
self.messages.removeAll()
for data in snapshot {
if let postDict = data.value as? Dictionary<String, AnyObject>
{
let key = data.key
let post = Message(messageKey: key, postData: postDict)
self.messages.append(post)
}
}
}
self.chatTableView.reloadData()
})
}//loadData
func moveToBottom() {
DispatchQueue.main.async {
if self.messages.count > 0 {
let indexPath = IndexPath(row: self.messages.count - 1, section: 0)
self.chatTableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
}
}
}
mainChatScreenTableViewCell
import UIKit
import SwiftKeychainWrapper
import Firebase
import FirebaseStorage
import FirebaseDatabase
class mainChatScreenTableViewCell: UITableViewCell {
#IBOutlet weak var recievedMessageLbl: UILabel!
#IBOutlet weak var recievedMessageView: UIView!
#IBOutlet weak var sentMessageLbl: UILabel!
#IBOutlet weak var sentMessageView: UIView!
#IBOutlet var receivedTimeLabel: UILabel!
#IBOutlet var sentTimeLabel: UILabel!
#IBOutlet var likeOrUnlikeImageView: UIImageView!
#IBOutlet var errorImageView: UIImageView!
#IBOutlet var checkImage: UIImageView!
var message: Message!
var currentUser = KeychainWrapper.standard.string(forKey: "uid")
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
sentMessageView.layer.masksToBounds = true
recievedMessageView.layer.masksToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func configCell(message: Message) {
self.message = message
print("message label::\(message.message.count)")
if message.sender == currentUser {
let time = message.receivedTimeStamp
let timeinterval : TimeInterval = time
let dateFromServer = NSDate(timeIntervalSince1970:timeinterval)
let formatter = DateFormatter()
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.ISO8601) as Calendar?
formatter.locale = NSLocale(localeIdentifier: "en_IN") as Locale
formatter.timeZone = NSTimeZone(name: "GMT+5:30") as TimeZone?
formatter.dateFormat = "h:mm a"
formatter.amSymbol = "AM"
formatter.pmSymbol = "PM"
let dateString: String = formatter.string(from: dateFromServer as Date)
print("dateString:::\(dateString)")
sentMessageView.isHidden = false
sentMessageView.layer.backgroundColor = UIColor.clear.cgColor
sentMessageLbl.text = " " + message.message
sentTimeLabel.text = " " + dateString
recievedMessageLbl.text = ""
recievedMessageLbl.isHidden = true
recievedMessageView.isHidden = true
} else {
let time = message.receivedTimeStamp
let timeinterval : TimeInterval = time
let dateFromServer = NSDate(timeIntervalSince1970:timeinterval)
let formatter = DateFormatter()
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.ISO8601) as Calendar?
formatter.locale = NSLocale(localeIdentifier: "en_IN") as Locale
formatter.timeZone = NSTimeZone(name: "GMT+5:30") as TimeZone?
formatter.dateFormat = "h:mm a"
formatter.amSymbol = "AM"
formatter.pmSymbol = "PM"
let dateString: String = formatter.string(from: dateFromServer as Date)
print("dateString:::\(dateString)")
sentMessageView.isHidden = true
sentMessageLbl.isHidden = true
sentMessageLbl.text = ""
recievedMessageLbl.text = " " + message.message
receivedTimeLabel.text = " " + dateString
recievedMessageLbl.isHidden = false
recievedMessageView.layer.backgroundColor = UIColor.clear.cgColor
}
}
}
Here is my screenshot:
I'm getting correct message count but messages are fully loaded.
Any help much appreciated pls...
use it. heightForRowAt for height of cell but you must check your constraint.
and also use UITableViewDelegate to use it
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
I'm currently building an app where you can read all your last 7 days HeartRate. Once you request the data it get displayed into a UITableView, whenever the data is loaded you can send the results via an email button. Then after the email body get filled up with all the DataHeart. I'm looking to get only the Time & Heartbeat Rate but i can't figured a way to parse it clearly. Also whenever I press the submit or cancel button I can't return to the previous screen. The app doesn't crash or any error, it just wont let me go back.
Here's my code block:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
getHealthKitPermission()
}
let healthStore = HKHealthStore()
var heartRateData: [HKSample]?
#IBOutlet weak var tblHeartRateData: UITableView!
#IBAction func getHeartRate(_ sender: Any) {
getTodaysHeartRate { (result) in
DispatchQueue.main.async {
self.heartRateData = result
self.tblHeartRateData.reloadData()
}
}
}
#IBAction func emailResult(_ sender: Any) {
self.sendEmail()
}
func getTodaysHeartRate(completion: (#escaping ([HKSample]) -> Void)) {
print("func")
let heartRateType:HKQuantityType = HKQuantityType.quantityType(forIdentifier: .heartRate)!
let startDate = Date() - 7 * 24 * 60 * 60
let endDate = Date()
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [])
let sortDescriptors = [
NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
]
let heartRateQuery = HKSampleQuery(sampleType: heartRateType,
predicate: predicate,
limit: Int(HKObjectQueryNoLimit),
sortDescriptors: sortDescriptors)
{ (query:HKSampleQuery, results:[HKSample]?, error:Error?) -> Void in
guard error == nil else { print("error"); return }
completion(results!)
}
healthStore.execute(heartRateQuery)
}
func sendEmail() {
if let currentHeartRate = heartRateData{
if MFMailComposeViewController.canSendMail() {
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
let result = formatter.string(from: date)
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self as? MFMailComposeViewControllerDelegate
mail.setToRecipients([""])
mail.setMessageBody("<p>Your Heart Rate is: \(currentHeartRate)<p>" + result, isHTML: true)
present(mail, animated: true)
} else {
//Do nothing
}
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true)
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return heartRateData?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! HeartDataTableViewCell
let heartRateUnit:HKUnit = HKUnit(from: "count/min")
let heartData = self.heartRateData?[indexPath.row]
guard let currData:HKQuantitySample = heartData as? HKQuantitySample else { return UITableViewCell()}
cell.labelTimes.text = "Times: \(startDateSring)"
cell.labelHeartRate.text = "Heart Rate: \(currData.quantity.doubleValue(for: heartRateUnit))"
let startDateFormatter = DateFormatter()
startDateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
startDateFormatter.timeZone = TimeZone.current
let startDateSring = startDateFormatter.string(from: currData.startDate)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return
}
}
Your email sending function should look something like this:
guard let currentHeartRate = heartRateData else {
return
}
guard MFMailComposeViewController.canSendMail() else {
// show alert
return
}
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
let mail = MFMailComposeViewController()
// note that your view controller must conform to MFMailComposeViewControllerDelegate
mail.mailComposeDelegate = self
mail.setToRecipients([""])
let heartRateUnit = HKUnit.count().unitDivided(by: .minute())
let quantityStrings = currentHeartRate
.compactMap { $0 as? HKQuantitySample }
.map {
"<p>Your Heart Rate is: \($0.quantity.doubleValue(for: heartRateUnit)) on \(formatter.string(from: $0.startDate)) </p>"
}
mail.setMessageBody(quantityStrings.joined(separator: "<br>"), isHTML: true)
present(mail, animated: true)
Note that you need to conform to the mail compose delegate, e.g.:
extension ViewController: MFMailComposeViewController {
}
I am getting error in ToDoViewController.Swift here is the overall code:
I am makeing a simple app for taking orders from customers. and orders will store in Firebase.
View Controller.Swift
import UIKit
import Firebase
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var todoList = [Todo]()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadData()
}
func loadData() {
self.todoList.removeAll()
let ref = FIRDatabase.database().reference()
ref.child("todoList").observeSingleEvent(of: .value, with: { (snapshot) in
if let todoDict = snapshot.value as? [String:AnyObject] {
for (_,todoElement) in todoDict {
print(todoElement);
let todo = Todo()
todo.name = todoElement["name"] as? String
todo.message = todoElement["message"] as? String
todo.reminderDate = todoElement["date"] as? String
self.todoList.append(todo)
}
}
self.tableView.reloadData()
}) { (error) in
print(error.localizedDescription)
}
}
//MARK: TableView datasource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.todoList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoCell")
cell!.textLabel?.text = todoList[indexPath.row].name
return cell!
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
ToDoViewController
import UIKit
import Firebase
class ToDoViewController: UIViewController {
var todo:Todo?
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var messageField: UITextField!
#IBOutlet weak var dateFormatter: UIDatePicker!
#IBAction func Done(_ sender: Any) {
if todo == nil {
todo = Todo()
}
// first section
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy hh:mm"
todo?.name = self.nameField.text
todo?.message = self.messageField.text
todo?.reminderDate = dateFormatter.string(from: self.dateFormatter.date)
//second section
let ref = FIRDatabase.database().reference()
let key = ref.child("todoList").childByAutoId().key
let dictionaryTodo = [ "name" : todo!.name! ,
"message" : todo!.message!,
"date" : todo!.reminderDate!]
let childUpdates = ["/todoList/\(key)": dictionaryTodo]
ref.updateChildValues(childUpdates, withCompletionBlock: { (error, ref) -> Void in
self.navigationController?.popViewController(animated: true)
})
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let todoVC = self.storyboard!.instantiateViewController(withIdentifier: "ToDoVC") as! ToDoViewController
todoVC.todo = todoList[indexPath.row]
self.navigationController?.pushViewController(todoVC, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if self.todo != nil {
nameField.text = self.todo?.name
messageField.text = self.todo?.message
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy hh:mm"
let date = dateFormatter.date(from: self.todo!.reminderDate!)
datePicker.date = date!
}
}
}
Todo.Swift
import UIKit
class Todo: NSObject {
var name :String?
var message: String?
var reminderDate: String?
// id which is set from firebase to uniquely identify it
var uniqueId:String?
}
Something is wrong with your code:
Use of un-resolved identifier 'todoList':
todoList is declared in View Controller.Swift and you cannot use it in ToDoViewController.
Cannot assign to property: 'date' is a method:
In the code datePicker is undefined and #IBOutlet weak var dateFormatter: UIDatePicker! should be:
#IBOutlet weak var datePicker: UIDatePicker!
AND In the image dateFormatter.date = date! should be:
datePicker.date = date!