首页 > 解决方案 > Swift - Parse Data Return in Email

问题描述

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
    }
}

标签: iosswiftfunctionparsing

解决方案


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 {
}

推荐阅读