MVC 简单示例:BMI-Calculator

项目结构项目结构

这是一个小 demo,根据用户的体重和身高,计算出他们的身体质量指数(BMI,Body Mass Index),并给出健康建议:多饮食、少饮食、继续保持现状。

  1. Models

BMI.swift 定义 BMI 基本属性

import UIKit

struct BMI {
    let value: Float
    let advice: String
    let color: UIColor
}

CalculatorBrain.swift 处理计算相关逻辑

import UIKit

struct CalculatorBrain {
    
    var bmi: BMI?
    
    func getBMIValue() -> String {
        let bmiTo1DecimalPlace = String(format: "%.1f", bmi?.value ?? 0.0)
        return bmiTo1DecimalPlace
    }
    
    func getAdvice() -> String {
        return bmi?.advice ?? "No advice"
    }
    
    func getColor() -> UIColor {
        return bmi?.color ?? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
    }
    
    mutating func calculateBMI(height: Float, weight: Float) {
        let bmiValue = weight / (height * height)

        if bmiValue < 18.5 {
            bmi = BMI(value: bmiValue, advice: "Eat more pies!", color: #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1))
        } else if bmiValue < 24.9 {
            bmi = BMI(value: bmiValue, advice: "Fit as a fiddle!", color: #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1))
        } else {
            bmi = BMI(value: bmiValue, advice: "Eat less pies!", color: #colorLiteral(red: 0.9098039269, green: 0.4784313738, blue: 0.6431372762, alpha: 1))
        }
    }
}

注意:这里使用的 struct 而不是 class。 结构体和类的区别是,前者为值引用,后者为对象引用。

假设有一张图片存在电脑某个路径,值引用情况,就是每次引用都会复制一张图片出来,在这里修改这个图片,其它地方不会受到影响。而对象引用就不同了,每个用户都会去电脑的那个路径查找、使用该图片,一旦某个用户修改了图片,其它人也会被影响到。

  1. Views

该模块下存放相应的视图。

  1. Controllers

CalculateViewController.swift

import UIKit

class CalculateViewController: UIViewController {
    
    var calculatorBrain = CalculatorBrain()

    @IBOutlet weak var heightLabel: UILabel!
    @IBOutlet weak var weightLabel: UILabel!
    @IBOutlet weak var heightSlider: UISlider!
    @IBOutlet weak var weightSlider: UISlider!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func heightSliderChanged(_ sender: UISlider) {
        let height = String(format: "%.2f", sender.value)
        heightLabel.text = "\(height)m"
    }
    
    @IBAction func weightSliderChanged(_ sender: UISlider) {
        let weight = String(format: "%.0f", sender.value)
        weightLabel.text = "\(weight)Kg"
    }
    
    @IBAction func calculatePressed(_ sender: UIButton) {
        let height = heightSlider.value
        let weight = weightSlider.value

        calculatorBrain.calculateBMI(height: height, weight: weight)
        performSegue(withIdentifier: "goToResult", sender: self)
        
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToResult" {
            let destinationVC = segue.destination as! ResultViewController
            destinationVC.bmiValue = calculatorBrain.getBMIValue()
            destinationVC.advice = calculatorBrain.getAdvice()
            destinationVC.color = calculatorBrain.getColor()
        }
    }
}

ResultViewController.swift

import UIKit

class ResultViewController: UIViewController {
    
    var bmiValue: String?
    var advice: String?
    var color: UIColor?

    @IBOutlet weak var bmiLabel: UILabel!
    @IBOutlet weak var adviceLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        bmiLabel.text = bmiValue
        adviceLabel.text = advice
        view.backgroundColor = color
    }
    
    @IBAction func recalculatePressed(_ sender: UIButton) {
        dismiss(animated: true, completion: nil)
    }
}

两个 Controller 控制两个页面。

最终效果:Calculator

源码路径:BMI-Calculator-iOS13

本文由博客一文多发平台 OpenWrite 发布!

以下是一个可能的JAVA实现,可以作为参考: ```java import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; public class WorkTimeCalculator { private String workPeriodStr; // 工作时间段字符串 private List<WorkPeriod> workPeriods = new ArrayList<>(); // 工作时间段列表 public WorkTimeCalculator(String workPeriodStr) { this.workPeriodStr = workPeriodStr; parseWorkPeriods(); } /** * 解析工作时间段字符串,生成工作时间段列表 */ private void parseWorkPeriods() { String[] periodStrs = workPeriodStr.split(";"); for (String periodStr : periodStrs) { String[] startEnd = periodStr.split("-"); if (startEnd.length != 2) { throw new IllegalArgumentException("Invalid work period string: " + periodStr); } WorkPeriod period = new WorkPeriod(parseTime(startEnd[0]), parseTime(startEnd[1])); workPeriods.add(period); } } /** * 解析时间字符串,生成Date对象 */ private Date parseTime(String timeStr) { SimpleDateFormat format = new SimpleDateFormat("HH:mm"); try { return format.parse(timeStr); } catch (ParseException e) { throw new IllegalArgumentException("Invalid time string: " + timeStr); } } /** * 计算工作时间段与给定日期时间的交集,返回每天的工作时间段 */ public List<String> calculateWorkTimes(Date startDateTime, Date endDateTime) { List<String> workTimes = new ArrayList<>(); Calendar calendar = Calendar.getInstance(); calendar.setTime(startDateTime); while (!calendar.getTime().after(endDateTime)) { Date date = calendar.getTime(); List<WorkPeriod> dayWorkPeriods = getDayWorkPeriods(date); if (dayWorkPeriods.isEmpty()) { // 当天没有工作时间段,跳过 calendar.add(Calendar.DATE, 1); continue; } // 计算当天的工作时间段 for (WorkPeriod period : dayWorkPeriods) { Date workStart = max(period.getStart(), date); Date workEnd = min(period.getEnd(), addDays(date, 1)); if (!workStart.after(workEnd)) { String workTimeStr = formatTime(workStart) + "-" + formatTime(workEnd); workTimes.add(workTimeStr); } } calendar.add(Calendar.DATE, 1); } return workTimes; } /** * 获取某一天的工作时间段 */ private List<WorkPeriod> getDayWorkPeriods(Date date) { List<WorkPeriod> dayWorkPeriods = new ArrayList<>(); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); for (WorkPeriod period : workPeriods) { if (isSameDay(period.getStart(), date) || isSameDay(period.getEnd(), date)) { // 时间段的起始或结束时间在该日期内,加入当天的工作时间段 dayWorkPeriods.add(period); } else if (period.getStart().before(date) && period.getEnd().after(addDays(date, 1))) { // 时间段跨越该日期,加入完整的时间段 dayWorkPeriods.add(period); } } return dayWorkPeriods; } /** * 判断两个日期是否为同一天 */ private boolean isSameDay(Date date1, Date date2) { Calendar cal1 = Calendar.getInstance(); cal1.setTime(date1); Calendar cal2 = Calendar.getInstance(); cal2.setTime(date2); return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && cal1.get(Calendar.DATE) == cal2.get(Calendar.DATE); } /** * 获取两个日期中较大的一个 */ private Date max(Date date1, Date date2) { return date1.after(date2) ? date1 : date2; } /** * 获取两个日期中较小的一个 */ private Date min(Date date1, Date date2) { return date1.before(date2) ? date1 : date2; } /** * 在给定日期上增加若干天 */ private Date addDays(Date date, int days) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DATE, days); return calendar.getTime(); } /** * 将Date对象格式化为HH:mm字符串 */ private String formatTime(Date time) { SimpleDateFormat format = new SimpleDateFormat("HH:mm"); return format.format(time); } /** * 工作时间段类,包含起始时间和结束时间 */ private static class WorkPeriod { private Date start; private Date end; public WorkPeriod(Date start, Date end) { this.start = start; this.end = end; } public Date getStart() { return start; } public Date getEnd() { return end; } } } ``` 使用示例: ```java String workPeriodStr = "08:00-09:00;10:00-11:00"; String startDateTimeStr = "2023-05-25 08:17:00"; String endDateTimeStr = "2023-05-26 10:20:00"; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date startDateTime = format.parse(startDateTimeStr); Date endDateTime = format.parse(endDateTimeStr); WorkTimeCalculator calculator = new WorkTimeCalculator(workPeriodStr); List<String> workTimes = calculator.calculateWorkTimes(startDateTime, endDateTime); for (String workTime : workTimes) { System.out.println(workTime); } ``` 输出结果: ``` 08:17-09:00 10:00-11:00 08:00-09:00 10:00-10:20 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值