前言:

师弟要毕业设计,就敲了swift版的计算器给他参考下。现在把代码放上来,通过这个计算器,可以学习简单的封装:将逻辑与界面分离并提供接口的编程方式,这也是我们学习面向对象的必要点。

基于 xcode 9.0 swift4.0

一、先引用SnapKit框架 SnapKit自己看git引入 利用其来约束组件

二、新建一个继承UIButton类的类文件,命名为DWFuncButton,对其设置字体、颜色、风格代码如下:

class DWFuncButton: UIButton {init() {super.init(frame: CGRect.zero)//为按钮添加边框self.layer.borderWidth = 0.5;self.layer.borderColor = UIColor(red: 219/255.0, green: 219/255.0, blue: 219/255.0, alpha: 1).cgColor//设置字体与字体颜色self.setTitleColor(UIColor.orange, for: .normal)self.titleLabel?.font = UIFont.systemFont(ofSize: 25)self.setTitleColor(UIColor.black, for: .highlighted)}required init?(coder aDecoder: NSCoder) {fatalError("init(coder:) has not been implemented")}}复制代码

三、创建一个继承UIView的类,命名为DWBoard,将其用作计算器的操作面板 首先引入SnapKit框架 import SnapKit 先创建一个数组属性,存放操作面板上的所有功能按钮标题

var dataArray = ["0", ".", "%", "=", "1", "2", "3", "+", "4", "5", "6", "-", "7", "8", "9", "*", "AC", "DEL", "^", "/"]
复制代码

重写父类的构造方法,在其中进行界面的加载操作:

override init(frame: CGRect) {super.init(frame: frame)setupUI()}
复制代码
//对界面进行布局
func setupUI() {//创建一个变量 用于保存当前布局按钮的上一个按钮var frontBtn: DWFuncButton!//进行功能按钮的循环创建for index in 0..<20 {//创建一个功能按钮let btn = DWFuncButton()self.addSubview(btn)//约束btn.snp.makeConstraints({ (make) in//当按钮每一行的第一个时,将其靠左侧摆放if index%4 == 0 {make.left.equalTo(0)}else { //否则将按钮的左边考上一个右侧进行摆放make.left.equalTo(frontBtn.snp.right)}//当按钮为第一行,将其靠父视图底部摆放if index/4 == 0 {make.bottom.equalTo(0)}else if index%4 == 0 { //当按钮不在第一行且为每行的第一个时,将其底部与上一个按钮的顶部对齐make.bottom.equalTo(frontBtn.snp.top)//否则将其底部与上一个按钮底部对齐整}else {make.bottom.equalTo(frontBtn.snp.bottom)}//约束宽度为父视图宽度的0.25倍make.width.equalTo(btn.superview!.snp.width).multipliedBy(0.25)//约束高度为父视图宽度的0.2倍make.height.equalTo(btn.superview!.snp.height).multipliedBy(0.2)})//设置tag值btn.tag = index + 100//添加点击事件btn.addTarget(self, action: #selector(btnClick(_:)), for: .touchUpInside)//设置标题btn.setTitle(dataArray[index], for: .normal)//对上一个按钮更新保存frontBtn = btn}}
复制代码

上面就构建了一个简单的键盘界面,约束代码大家可以看一下,排版为5行4列,布局顺序为从下向上、从左向右依次布局

创建上述代码的点击方法

@objc func btnClick(_ button:DWFuncButton) {print(button.currentTitle as Any)}
复制代码

用户在操作面板上进行输入操作,在计算器的显示屏上还需要显示输入的内容,同时,显示屏还兼有计算结果的功能。 首先在DWCalculator工程上新建一个名为DWScreen的类文件,继承自UIView,作为计算器的显示器控件。显示屏分成两部分,一部分用于计算结果,一部分用于显示用户输入的计算过程,所以用两个UILabel来处理。

class DWScreen: UIView {var inputLabel:UILabel?//用于显示历史记录信息var historyLabel:UILabel?//用户输入表达式或者计算结果字符串var inputString = ""//历史表达式字符串var historyString = ""//所有数字字符 用于进行检测匹配let figureArray:Array<Character> = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."]//所有运算功能字符 用于进行检测匹配let funcArray = ["+", "-", "*", "/", "^"]init() {super.init(frame: CGRect.zero)inputLabel = UILabel()historyLabel = UILabel()setupUI()}func setupUI() {//设置文字的对其方式为右对齐inputLabel?.textAlignment = .righthistoryLabel?.textAlignment = .right//设置字体inputLabel?.font = UIFont.systemFont(ofSize: 34)historyLabel?.font = UIFont.systemFont(ofSize: 30)//设置文字颜色inputLabel?.textColor = UIColor.orangehistoryLabel?.textColor = UIColor.black//设置文字大小根据字数进行适配inputLabel?.adjustsFontSizeToFitWidth = trueinputLabel?.minimumScaleFactor = 0.5  //最小字体为当前字体的一半historyLabel?.adjustsFontSizeToFitWidth = truehistoryLabel?.minimumScaleFactor = 0.5//设置文字的截断方式inputLabel?.lineBreakMode = .byTruncatingHeadhistoryLabel?.lineBreakMode = .byTruncatingHead//设置文字的行数inputLabel?.numberOfLines = 0historyLabel?.numberOfLines = 0self.addSubview(inputLabel!)self.addSubview(historyLabel!)//进行自动布局inputLabel?.snp.makeConstraints({ (make) inmake.left.equalTo(10)make.right.equalTo(-10)make.bottom.equalTo(-10)make.height.equalTo(inputLabel!.superview!.snp.height).multipliedBy(0.5).offset(-10)})historyLabel?.snp.makeConstraints({ (make) inmake.left.equalTo(10)make.right.equalTo(-10)make.top.equalTo(10)make.height.equalTo(inputLabel!.superview!.snp.height).multipliedBy(0.5).offset(-10)})}//提供一个输入信息的接口func inputContent(content:String) {inputString.append(content)inputLabel?.text = inputString}//提供一个刷新历史记录的方法func refreshHistory() {historyString = inputStringhistoryLabel?.text = historyString}required init?(coder aDecoder: NSCoder) {fatalError("init(coder:) has not been implemented")}}
复制代码

DWBoard类可以接收用户的输入,DWScreen需要获取用户的输入,他们之间的关联是需要通过ViewController类来完成的。使用代理设计模式完成此功能。

在DWBoard.swift添加协议代码

protocol DWBoardButtonInputDelegate {func boardButtonClick(content:String)
}
复制代码

在DWBoard类添加一个代理属性:

var delegate:DWBoardButtonInputDelegate?
复制代码

修改DWBoard类中的点击事件

@objc func btnClick(_ button:DWFuncButton) {if delegate != nil {//通过协议方法将值传递出去delegate?.boardButtonClick(content: button.currentTitle!)}
}
复制代码

ViewController类也需要将DWBoard类实例和DWScreen类实例作为自己的属性,相互调用

let board = DWBoard()
let screen = DWScreen()
复制代码

在viewDidLoad()方法添加setupUI(),并且setupUI代码如下

func setupUI() {self.view.addSubview(board)//设置代理board.delegate = selfboard.snp.makeConstraints { (make) inmake.left.equalTo(0)make.right.equalTo(0)make.bottom.equalTo(0)make.height.equalTo(board.superview!.snp.height).multipliedBy(2/3.0)}self.view.addSubview(screen)screen.snp.makeConstraints { (make) inmake.left.equalTo(0)make.right.equalTo(0)make.top.equalTo(0)make.bottom.equalTo(board.snp.top)}
}
复制代码

viewController需要遵守DWBoardButtonInputDelegate协议:

class ViewController: UIViewController,DWBoardButtonInputDelegate
复制代码

并且实现协议方法:

func boardButtonClick(content: String) {if content == "AC" || content == "DEL" || content == "=" {//进行逻辑处理screen.refreshHistory()}else {screen.inputContent(content:content)}
}
复制代码

运行项目,如下图:

界面部分我们已经基本开发完,接下来进行逻辑处理类的封装。

三、计算器计算逻辑: DWScreen类需要继续完善。例如当用户点击清空按钮时,输入的计算表达就应该被清空。当用户点击回退按钮时,上一次输入的字符就应该被清空。在DWScreen类添加如下代码:

//清空显示屏当前输入的信息
func clearContent() {inputString = ""
}//删除显示屏中上次输入的字符
func deleteInput() {if inputString.characters.count>0 {inputString.remove(at: inputString.index(before: inputString.endIndex))inputLabel?.text = inputString}
}
复制代码

在项目中新建一个继承于NSObject的类文件,并命名为DWCalculatorEngine。将其作为计算引擎工具类,代码如下:

class DWCalculatorEngine: NSObject {//运算符集合let funcArray:CharacterSet = ["+", "-", "*", "/", "^", "%"]func calculatEquation(equation:String)->Double {//以运算符进行分割获取到所有数字let elementArray = equation.components(separatedBy: funcArray)//设置一个运算标记游标var tip = 0//运算结果var result:Double = Double(elementArray[0])!//遍历计算表达式for char in equation.characters {switch char {//进行加法运算case "+":tip += 1if elementArray.count>tip {result += Double(elementArray[tip])!}//进行减法运算case "-":tip += 1if elementArray.count>tip {result -= Double(elementArray[tip])!}case "*":tip += 1if elementArray.count>tip {result *= Double(elementArray[tip])!}//进行除法运算case "/":tip += 1if elementArray.count>tip {result /= Double(elementArray[tip])!}//进行取余运算case "%":tip += 1if elementArray.count>tip {result = Double(Int(result)%Int(elementArray[tip])!)}//进行指数运算case "^":tip += 1if elementArray.count>tip {let tmp = resultfor _ in 1..<Int(elementArray[tip])! {result *= tmp}}default:break}}return result}
}
复制代码

在ViewController类中添加两个属性:一个计算工具类:

//计算引擎实例
let calcalator = DWCalculatorEngine()
//这个输入是否需要刷新显示屏
var isNew = false
复制代码

isNew属性主要作用是标记本次输入是否需要将显示屏已有的内容清除。当用户完成一次计算后,计算结果会显示在显示屏上。此时如果用户继续输入,则进行下一轮的计算,显示屏的上次结果应该被清空。 修改ViewController类中的协议方法

func boardButtonClick(content: String) {if content == "AC" || content == "DEL" || content == "=" {//进行逻辑处理switch content {case "AC":screen.clearContent()screen.refreshHistory()case "DEL":screen.deleteInput()case "=":let result = calcalator.calculatEquation(equation: screen.inputString)//先刷新历史screen.refreshHistory()//清除输入的内容screen.clearContent()//将结果输入screen.inputContent(content: String(result))isNew = truedefault:screen.refreshHistory()}}else {if isNew {screen.clearContent()isNew = false}screen.inputContent(content:content)}
}
复制代码

大功告成!代码传送门

Swift封装 计算器开发相关推荐

  1. OC与Swift封装网络工具类

    2019独角兽企业重金招聘Python工程师标准>>> AFNetworking ATS 设置 <key>NSAppTransportSecurity</key&g ...

  2. Qt计算器开发(二):信号槽实现数学表达式合法性检查

    表达式的合法性 由于我们的计算器不是单步计算的,所以我们能够一次性输入一个长表达式.然而假设用户输入的长表达式不合法的话,那么就会引发灾难.所以有必要对于用户的输入做一个限制. 一些限制举例: 比方, ...

  3. 科学计算机java算法实现,(Java)科学型计算器开发及实现.doc

    (Java)科学型计算器开发及实现 淮北师范大学 科学型计算器的开发与实现 学 院 计算机科学与技术 专 业学 生 姓 名学 号指导教师姓名科学型计算器的开发与实现 作 者: 指导教师: 摘 要:目前 ...

  4. xcode13 swift语言 ios开发 快捷代码优化方式(代码重构)例子

    xcode13 swift语言 ios开发 快捷代码优化方式(代码重构)例子 这是自己在CSDN上发的第二篇文章,开始用markdown编辑,更加美观一些. 问题描述 在用xcode swift语言开 ...

  5. swift python混合开发_引用swift项目

    iOS - OC 与 Swift 互相操作 前言 在 Swift 语言中,我们可以使用 Objective-C.C 语言编写代码,我们可以导入任意用 Objective-C 写的 Cocoa 平台框架 ...

  6. 学习Swift:经验丰富的开发人员指南

    因此,您的老板希望您学习iOS应用开发. 或者,也许您有一个要处理的应用程序侧项目. 你从哪里开始? 学习新平台和编程语言可能会令人生畏. 即使您尝试学习基础知识,也会不断发布新技术,从而很难保持最新 ...

  7. Java交互界面实现计算器开发设计【附函数源码】

    使用Java开发的简易计算器,包括加.减.乘.除.平方.立方.小数等运算,适合学习GUI编程实践, 目录 控件触发时集中处理函数 操作符点击后数据转换赋值函数 计算器窗口界面函数 运算符控件 数字控件 ...

  8. linux下swift编程教程视频教程,Ubuntu 14.04下搭建 Swift 3.0 开发环境教学视频+PPT

    分享Ubuntu 14.04下搭建 Swift 3.0 开发环境教学视频+PPT. Linux版本:Ubuntu: 14.04 LTS Swift: 3.0 到https://swift.org/do ...

  9. 《Swift iOS应用开发实战》——2.2 了解故事板

    本节书摘来自华章计算机<Swift iOS应用开发实战>一书中的第2章,第2.2节,作者:刘铭 著, 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2.2 了 ...

最新文章

  1. 1.1.1 概念、组成、功能和分类
  2. 【数据挖掘笔记六】挖掘频繁模式、关联和相关性:基本概念和方法
  3. Python中的集合
  4. IntelliJ IDEA2017 激活方法 最新的
  5. 谷歌大改Transformer注意力,速度、内存利用率都提上去了-新的 Transformer 架构——Performer
  6. linux 7查内核,查看CentOS7内核版本及发行版本
  7. 【VB.NET】VB.NET文件问题的解答
  8. IIS服务在启动默认网站(停止)时显示发生意外错误0x8ffe2740,
  9. 限制码率的视频编码标准比较(包括MPEG-2,H.263, MPEG-4,以及 H.264)
  10. 汇编3-返回以及优化
  11. Python图像增强之直方图均衡化(全局直方图均衡、局部直方图均衡)
  12. DHU Matlab Experiment【4】_验证非线性最小二乘拟合lsqcurvefit()函数中的误差平方和
  13. java判断闰年中闰月_2019年农历闰几月 关于闰年闰月的认识
  14. 智能客服在2022:从成本中心奔向价值中心
  15. c语言atan,C语言atan()函数:求正切值为 x 的弧度数
  16. 固态硬盘是什么接口_了解移动固态硬盘接口知识,告诉你PSSD到底能多快
  17. vmware 提示该虚拟机正在使用中
  18. Python的return语句中使用条件判断
  19. 六、java版商城之一件代发设置 Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入驻商城 直播带货商城 电子商务
  20. 自动驾驶系统入门(一) - 环境感知

热门文章

  1. 论坛推广的6个方法和注意事项【转】
  2. 《项目管理实战十步法》--方正证券培训圆满成功
  3. ExtJS中xtype一览
  4. kf.qq.lol.html,英雄联盟手游预约FAQ
  5. 程序员:如何正确使用你的黄金时间
  6. python机器人视觉编程——入门篇(下)
  7. 解决IDEA中 XML文件屎黄色背景 的方法
  8. java字符串的拆分_Java中的字符串分割 .
  9. 安川服务器维修手册,安川驱动器维修常见报警代码及维修方法
  10. 如何用纯 CSS 创作一个金属光泽 3D 按钮特效