XCode Interface Builder开发——2


简单的练手项目--仿苹果自备的计算器

简介

制作一个简易功能的计算器并非难事,但是其中要考虑的不同情况却仍有许多,稍不留神就会踩坑。

例如:

  • 在输入完运算符后如果直接输入负号或者小数点的情况
  • 连续运算的情况
  • 在输入等号后继续运算或直接输入数字进行下一轮的计算的情况
  • 小数情况下,精度带来的问题
  • ... ...

设计思想

按照编译原理中的三元式的思想,为了区分输入的第一运算对象和第二运算对象,我分别将其命名为firstNum和secondNum,并将它们作为ViewController的属性。并且为了区分计算器当前处于何种模式下(点击小数点后的小数模式、点击负号的负号模式、待第二个数输入的模式等等),我又将各种不同的BOOL型变量设置为其属性供各种方法下调用。


话不多说,看代码:

  1. //
  2. // ViewController.m
  3. // MyFirstApp
  4. //
  5. // Created by solist on 2019/1/31.
  6. // Copyright © 2019 solist. All rights reserved.
  7. //
  8. #import "ViewController.h"
  9. @interface ViewController ()
  10. @property(nonatomic) double firstNum;
  11. @property(nonatomic) double secondNum;
  12. @property(nonatomic) BOOL fistNumIsActive;
  13. @property(nonatomic) BOOL isWaitingForSecondNum;
  14. @property(nonatomic) BOOL isTappingSecondNum;
  15. @property(nonatomic) BOOL isNegativeNum;
  16. @property(nonatomic) BOOL isBeginNegativeNum;
  17. @property(nonatomic) BOOL isAfterEqual;
  18. @property(nonatomic) BOOL isTappingDecimals;
  19. @property(nonatomic) float decimalRecord;
  20. @property(nonatomic,weak) NSString *operation;
  21. @property (weak, nonatomic) IBOutlet UITextField *result;
  22. @end
  23. @implementation ViewController
  24. //初始化属性
  25. - (void)viewDidLoad {
  26. [super viewDidLoad];
  27. // Do any additional setup after loading the view, typically from a nib.
  28. _firstNum=0.0;
  29. _secondNum=0.0;
  30. _fistNumIsActive=YES;
  31. _isTappingSecondNum=NO;
  32. _isWaitingForSecondNum=NO;
  33. _isNegativeNum=NO;
  34. _isBeginNegativeNum=NO;
  35. _isAfterEqual=NO;
  36. _isTappingDecimals=NO;
  37. _decimalRecord=0.1;
  38. [self updateScreen:0.0];
  39. }
  40. //更新屏幕数据(对象方法,在不同的按钮响应事件中调用)
  41. -(void)updateScreen:(double) num{
  42. _result.text=[NSString stringWithFormat:@"%f", num];
  43. }
  44. //清空(与清空“AC”的Btn连接)
  45. - (IBAction)AC {
  46. _result.text=@"0";
  47. _firstNum=0.0;
  48. _secondNum=0.0;
  49. //更新数据
  50. [self updateScreen:_firstNum];
  51. _fistNumIsActive=YES;
  52. _isWaitingForSecondNum=NO;
  53. _isTappingSecondNum=NO;
  54. _isNegativeNum=NO;
  55. _isBeginNegativeNum=NO;
  56. _isAfterEqual=NO;
  57. _isTappingDecimals=NO;
  58. _decimalRecord=0.1;
  59. _operation=@"nil";
  60. }
  61. //正负数转换(与负号“-”的Btn连接)
  62. - (IBAction)pnConversion{
  63. if(_isWaitingForSecondNum||_firstNum==0){
  64. _isBeginNegativeNum=!_isBeginNegativeNum;
  65. _isNegativeNum=!_isNegativeNum;
  66. //_secondNum=0;
  67. _isWaitingForSecondNum=NO;
  68. if(_isBeginNegativeNum&&!_isAfterEqual){
  69. [self updateScreen:-0.0];
  70. }
  71. else if(_isAfterEqual){
  72. _firstNum=-_firstNum;
  73. [self updateScreen:_firstNum];
  74. }
  75. else{
  76. [self updateScreen:+0.f];
  77. }
  78. }
  79. else{
  80. _isNegativeNum=!_isNegativeNum;
  81. if(!_isTappingSecondNum){
  82. //修改第一个数的符号位
  83. _firstNum=0-_firstNum;
  84. [self updateScreen:_firstNum];
  85. }
  86. else{
  87. if(_fistNumIsActive){
  88. //当修改数为结果时
  89. //修改第一个数的符号位
  90. _firstNum=0-_firstNum;
  91. [self updateScreen:_firstNum];
  92. }
  93. else{
  94. //修改第二个数的符号位
  95. _secondNum=0-_secondNum;
  96. if(_firstNum==0){
  97. _firstNum=-0.0;
  98. }
  99. [self updateScreen:_secondNum];
  100. }
  101. }
  102. }
  103. }
  104. //百分号转换(与百分号“%”的Btn连接)
  105. - (IBAction)percentageConversion {
  106. if(!_isTappingSecondNum)
  107. {
  108. //将第一个数改为百分数
  109. _firstNum=_firstNum/100.0;
  110. [self updateScreen:_firstNum];
  111. }
  112. else{
  113. if(_fistNumIsActive){
  114. //当修改数为结果时
  115. //将第一个数改为百分数
  116. _firstNum=_firstNum/100.0;
  117. [self updateScreen:_firstNum];
  118. }
  119. else{
  120. //将第二个数改为百分数
  121. _secondNum=_secondNum/100.0;
  122. [self updateScreen:_secondNum];
  123. }
  124. }
  125. }
  126. //除法(与乘号“x”的Btn连接)
  127. - (IBAction)divide {
  128. //取消小数功能
  129. _decimalRecord=0.1;
  130. //1、输入等号后继续输入的情况
  131. if(_isAfterEqual){
  132. _isAfterEqual=!_isAfterEqual;
  133. }
  134. _isNegativeNum=NO;
  135. _isBeginNegativeNum=NO;
  136. //2、连续输入的情况
  137. if(_isTappingSecondNum){
  138. NSArray *operationsArray = @[@"add", @"sub", @"multi",@"divide"];
  139. //获得上次的运算符
  140. NSUInteger item = [operationsArray indexOfObject:_operation];
  141. float theResult;
  142. switch (item) {
  143. case 0:
  144. theResult=_firstNum+_secondNum;
  145. break;
  146. case 1:
  147. theResult=_firstNum-_secondNum;
  148. break;
  149. case 2:
  150. theResult=_firstNum*_secondNum;
  151. break;
  152. case 3:
  153. theResult=_firstNum/_secondNum;
  154. default:
  155. break;
  156. }
  157. //在屏幕上输出结果
  158. [self updateScreen:theResult];
  159. //更新firstNum
  160. _firstNum=theResult;
  161. }
  162. //更新firstNum
  163. _firstNum=[_result.text floatValue];
  164. //修改运算符号,并通知下一步为输入secondNum
  165. _isWaitingForSecondNum=YES;
  166. _fistNumIsActive=NO;
  167. _secondNum=0;
  168. _operation=@"divide";
  169. _isTappingSecondNum=NO;
  170. _isTappingDecimals=NO;
  171. }
  172. //乘法(与乘号“✖️”的Btn连接)
  173. - (IBAction)multi {
  174. //取消小数功能
  175. _decimalRecord=0.1;
  176. if(_isAfterEqual){
  177. _isAfterEqual=!_isAfterEqual;
  178. }
  179. _isNegativeNum=NO;
  180. _isBeginNegativeNum=NO;
  181. //连续输入的情况
  182. if(_isTappingSecondNum){
  183. NSArray *operationsArray = @[@"add", @"sub", @"multi",@"divide"];
  184. //获得上次的运算符
  185. NSUInteger item = [operationsArray indexOfObject:_operation];
  186. float theResult;
  187. switch (item) {
  188. case 0:
  189. theResult=_firstNum+_secondNum;
  190. break;
  191. case 1:
  192. theResult=_firstNum-_secondNum;
  193. break;
  194. case 2:
  195. theResult=_firstNum*_secondNum;
  196. break;
  197. case 3:
  198. theResult=_firstNum/_secondNum;
  199. default:
  200. break;
  201. }
  202. //在屏幕上输出结果
  203. [self updateScreen:theResult];
  204. //更新firstNum
  205. _firstNum=theResult;
  206. }
  207. //更新firstNum
  208. _firstNum=[_result.text floatValue];
  209. //修改运算符号,并通知下一步为输入secondNum
  210. _isWaitingForSecondNum=YES;
  211. _fistNumIsActive=NO;
  212. _secondNum=0;
  213. _operation=@"multi";
  214. _isTappingSecondNum=NO;
  215. _isTappingDecimals=NO;
  216. }
  217. //减法(与减号“-”的Btn连接)
  218. - (IBAction)sub {
  219. //取消小数功能
  220. _decimalRecord=0.1;
  221. if(_isAfterEqual){
  222. _isAfterEqual=!_isAfterEqual;
  223. }
  224. _isNegativeNum=NO;
  225. _isBeginNegativeNum=NO;
  226. //连续输入的情况
  227. if(_isTappingSecondNum){
  228. NSArray *operationsArray = @[@"add", @"sub", @"multi",@"divide"];
  229. //获得上次的运算符
  230. NSUInteger item = [operationsArray indexOfObject:_operation];
  231. float theResult;
  232. switch (item) {
  233. case 0:
  234. theResult=_firstNum+_secondNum;
  235. break;
  236. case 1:
  237. theResult=_firstNum-_secondNum;
  238. break;
  239. case 2:
  240. theResult=_firstNum*_secondNum;
  241. break;
  242. case 3:
  243. theResult=_firstNum/_secondNum;
  244. default:
  245. break;
  246. }
  247. //在屏幕上输出结果
  248. [self updateScreen:theResult];
  249. //更新firstNum
  250. _firstNum=theResult;
  251. }
  252. //更新firstNum
  253. _firstNum=[_result.text floatValue];
  254. //修改运算符号,并通知下一步为输入secondNum
  255. _isWaitingForSecondNum=YES;
  256. _fistNumIsActive=NO;
  257. _secondNum=0;
  258. _operation=@"sub";
  259. _isTappingSecondNum=NO;
  260. _isTappingDecimals=NO;
  261. }
  262. //加法(与“+”的Btn连接)
  263. - (IBAction)add {
  264. //取消小数功能
  265. _decimalRecord=0.1;
  266. if(_isAfterEqual){
  267. _isAfterEqual=!_isAfterEqual;
  268. }
  269. _isNegativeNum=NO;
  270. _isBeginNegativeNum=NO;
  271. //连续输入的情况
  272. if(_isTappingSecondNum){
  273. NSArray *operationsArray = @[@"add", @"sub", @"multi",@"divide"];
  274. //获得上次的运算符
  275. NSUInteger item = [operationsArray indexOfObject:_operation];
  276. float theResult;
  277. switch (item) {
  278. case 0:
  279. theResult=_firstNum+_secondNum;
  280. break;
  281. case 1:
  282. theResult=_firstNum-_secondNum;
  283. break;
  284. case 2:
  285. theResult=_firstNum*_secondNum;
  286. break;
  287. case 3:
  288. theResult=_firstNum/_secondNum;
  289. default:
  290. break;
  291. }
  292. //在屏幕上输出结果
  293. [self updateScreen:theResult];
  294. //更新firstNum
  295. _firstNum=theResult;
  296. }
  297. //更新firstNum
  298. _firstNum=[_result.text floatValue];
  299. //修改运算符号,并通知下一步为输入secondNum
  300. _isWaitingForSecondNum=YES;
  301. _fistNumIsActive=NO;
  302. _secondNum=0;
  303. _operation=@"add";
  304. _isTappingSecondNum=NO;
  305. _isTappingDecimals=NO;
  306. }
  307. //等号(与等号的Btn连接)
  308. - (IBAction)equal {
  309. //取消小数功能
  310. _decimalRecord=0.1;
  311. _isNegativeNum=NO;
  312. _isBeginNegativeNum=NO;
  313. _isTappingSecondNum=NO;
  314. NSArray *operationsArray = @[@"add", @"sub", @"multi",@"divide"];
  315. NSUInteger item = [operationsArray indexOfObject:_operation];
  316. //特殊情况:secondNum未输入,按secondNum=firstNum
  317. if(_isWaitingForSecondNum){
  318. _secondNum=_firstNum;
  319. }
  320. //进行计算
  321. float theResult;
  322. BOOL error=NO;
  323. switch (item) {
  324. case 0:
  325. theResult=_firstNum+_secondNum;
  326. break;
  327. case 1:
  328. theResult=_firstNum-_secondNum;
  329. break;
  330. case 2:
  331. theResult=_firstNum*_secondNum;
  332. break;
  333. case 3:
  334. if(_secondNum==0.0){
  335. error=YES;
  336. }else{
  337. theResult=_firstNum/_secondNum;
  338. }
  339. break;
  340. default:
  341. //当无运算符时,即清空后只输入了firstNum
  342. theResult=_firstNum;
  343. break;
  344. }
  345. //在屏幕上输出结果
  346. if(error){
  347. //输出错误提示
  348. _result.text=@"错误";
  349. _firstNum=0.0;
  350. }
  351. else{
  352. [self updateScreen:theResult];
  353. }
  354. //为下一次计算做准备
  355. _firstNum=theResult;
  356. _secondNum=0.0;
  357. _fistNumIsActive=YES;
  358. _isWaitingForSecondNum=YES;
  359. _isTappingSecondNum=NO;
  360. _isBeginNegativeNum=NO;
  361. _isNegativeNum=NO;
  362. _isAfterEqual=YES;
  363. }
  364. //点击数字1(与数字1的Btn连接)
  365. - (IBAction)_1 {
  366. //进行下一轮的计算
  367. if(_isAfterEqual){
  368. [self AC];
  369. }
  370. if(_fistNumIsActive){
  371. //正在输入第一个数
  372. if(_isNegativeNum){
  373. if(_isTappingDecimals){
  374. //输入了小数点模式后
  375. _firstNum=_firstNum-1.0*_decimalRecord;
  376. _decimalRecord*=0.1;
  377. }
  378. else{
  379. _firstNum=_firstNum*10.0-1.0;
  380. }
  381. }
  382. else{
  383. if(_isTappingDecimals){
  384. //输入了小数点模式后
  385. _firstNum=_firstNum+1.0*_decimalRecord;
  386. _decimalRecord*=0.1;
  387. }
  388. else{
  389. _firstNum=_firstNum*10.0+1.0;
  390. }
  391. }
  392. //更新屏幕
  393. [self updateScreen:_firstNum];
  394. _isWaitingForSecondNum=NO;
  395. }
  396. else{
  397. //正在输入第二个数
  398. _isTappingSecondNum=YES;
  399. if(_isNegativeNum){
  400. //_secondNum=_secondNum*10.f-1.f;
  401. if(_isTappingDecimals){
  402. _secondNum=_secondNum-1.f*_decimalRecord;
  403. _decimalRecord*=0.1;
  404. }
  405. else{
  406. _secondNum=_secondNum*10.f-1.f;
  407. }
  408. }
  409. else{
  410. //_secondNum=_secondNum*10.f+1.f;
  411. if(_isTappingDecimals){
  412. _secondNum=_secondNum+1.f*_decimalRecord;
  413. _decimalRecord*=0.1;
  414. }
  415. else{
  416. _secondNum=_secondNum*10.f+1.f;
  417. }
  418. }
  419. //更新屏幕
  420. [self updateScreen:_secondNum];
  421. _isWaitingForSecondNum=NO;
  422. }
  423. }
  424. - (IBAction)_2 {
  425. //进行下一轮的计算
  426. if(_isAfterEqual){
  427. [self AC];
  428. }
  429. if(_fistNumIsActive){
  430. //正在输入第一个数
  431. if(_isNegativeNum){
  432. if(_isTappingDecimals){
  433. //输入了小数点模式后
  434. _firstNum=_firstNum-2.0*_decimalRecord;
  435. _decimalRecord*=0.1;
  436. }
  437. else{
  438. _firstNum=_firstNum*10.0-2.0;
  439. }
  440. }
  441. else{
  442. if(_isTappingDecimals){
  443. //输入了小数点模式后
  444. _firstNum=_firstNum+2.0*_decimalRecord;
  445. _decimalRecord*=0.1;
  446. }
  447. else{
  448. _firstNum=_firstNum*10.0+2.0;
  449. }
  450. }
  451. //更新屏幕
  452. [self updateScreen:_firstNum];
  453. _isWaitingForSecondNum=NO;
  454. }
  455. else{
  456. //正在输入第二个数
  457. _isTappingSecondNum=YES;
  458. if(_isNegativeNum){
  459. //_secondNum=_secondNum*10.f-1.f;
  460. if(_isTappingDecimals){
  461. _secondNum=_secondNum-2.f*_decimalRecord;
  462. _decimalRecord*=0.1;
  463. }
  464. else{
  465. _secondNum=_secondNum*10.f-2.f;
  466. }
  467. }
  468. else{
  469. //_secondNum=_secondNum*10.f+1.f;
  470. if(_isTappingDecimals){
  471. _secondNum=_secondNum+2.f*_decimalRecord;
  472. _decimalRecord*=0.1;
  473. }
  474. else{
  475. _secondNum=_secondNum*10.f+2.f;
  476. }
  477. }
  478. //更新屏幕
  479. [self updateScreen:_secondNum];
  480. _isWaitingForSecondNum=NO;
  481. }
  482. }
  483. - (IBAction)_3 {
  484. //进行下一轮的计算
  485. if(_isAfterEqual){
  486. [self AC];
  487. }
  488. if(_fistNumIsActive){
  489. //正在输入第一个数
  490. if(_isNegativeNum){
  491. if(_isTappingDecimals){
  492. //输入了小数点模式后
  493. _firstNum=_firstNum-3.0*_decimalRecord;
  494. _decimalRecord*=0.1;
  495. }
  496. else{
  497. _firstNum=_firstNum*10.0-3.0;
  498. }
  499. }
  500. else{
  501. if(_isTappingDecimals){
  502. //输入了小数点模式后
  503. _firstNum=_firstNum+3.0*_decimalRecord;
  504. _decimalRecord*=0.1;
  505. }
  506. else{
  507. _firstNum=_firstNum*10.0+3.0;
  508. }
  509. }
  510. //更新屏幕
  511. [self updateScreen:_firstNum];
  512. _isWaitingForSecondNum=NO;
  513. }
  514. else{
  515. //正在输入第二个数
  516. _isTappingSecondNum=YES;
  517. if(_isNegativeNum){
  518. //_secondNum=_secondNum*10.f-1.f;
  519. if(_isTappingDecimals){
  520. _secondNum=_secondNum-3.f*_decimalRecord;
  521. _decimalRecord*=0.1;
  522. }
  523. else{
  524. _secondNum=_secondNum*10.f-3.f;
  525. }
  526. }
  527. else{
  528. //_secondNum=_secondNum*10.f+1.f;
  529. if(_isTappingDecimals){
  530. _secondNum=_secondNum+3.f*_decimalRecord;
  531. _decimalRecord*=0.1;
  532. }
  533. else{
  534. _secondNum=_secondNum*10.f+3.f;
  535. }
  536. }
  537. //更新屏幕
  538. [self updateScreen:_secondNum];
  539. _isWaitingForSecondNum=NO;
  540. }
  541. }
  542. - (IBAction)_4 {
  543. //进行下一轮的计算
  544. if(_isAfterEqual){
  545. [self AC];
  546. }
  547. if(_fistNumIsActive){
  548. //正在输入第一个数
  549. if(_isNegativeNum){
  550. if(_isTappingDecimals){
  551. //输入了小数点模式后
  552. _firstNum=_firstNum-4.0*_decimalRecord;
  553. _decimalRecord*=0.1;
  554. }
  555. else{
  556. _firstNum=_firstNum*10.0-4.0;
  557. }
  558. }
  559. else{
  560. if(_isTappingDecimals){
  561. //输入了小数点模式后
  562. _firstNum=_firstNum+4.0*_decimalRecord;
  563. _decimalRecord*=0.1;
  564. }
  565. else{
  566. _firstNum=_firstNum*10.0+4.0;
  567. }
  568. }
  569. //更新屏幕
  570. [self updateScreen:_firstNum];
  571. _isWaitingForSecondNum=NO;
  572. }
  573. else{
  574. //正在输入第二个数
  575. _isTappingSecondNum=YES;
  576. if(_isNegativeNum){
  577. //_secondNum=_secondNum*10.f-1.f;
  578. if(_isTappingDecimals){
  579. _secondNum=_secondNum-4.f*_decimalRecord;
  580. _decimalRecord*=0.1;
  581. }
  582. else{
  583. _secondNum=_secondNum*10.f-4.f;
  584. }
  585. }
  586. else{
  587. //_secondNum=_secondNum*10.f+1.f;
  588. if(_isTappingDecimals){
  589. _secondNum=_secondNum+4.f*_decimalRecord;
  590. _decimalRecord*=0.1;
  591. }
  592. else{
  593. _secondNum=_secondNum*10.f+4.f;
  594. }
  595. }
  596. //更新屏幕
  597. [self updateScreen:_secondNum];
  598. _isWaitingForSecondNum=NO;
  599. }
  600. }
  601. - (IBAction)_5 {
  602. //进行下一轮的计算
  603. if(_isAfterEqual){
  604. [self AC];
  605. }
  606. if(_fistNumIsActive){
  607. //正在输入第一个数
  608. if(_isNegativeNum){
  609. if(_isTappingDecimals){
  610. //输入了小数点模式后
  611. _firstNum=_firstNum-5.0*_decimalRecord;
  612. _decimalRecord*=0.1;
  613. }
  614. else{
  615. _firstNum=_firstNum*10.0-5.0;
  616. }
  617. }
  618. else{
  619. if(_isTappingDecimals){
  620. //输入了小数点模式后
  621. _firstNum=_firstNum+5.0*_decimalRecord;
  622. _decimalRecord*=0.1;
  623. }
  624. else{
  625. _firstNum=_firstNum*10.0+5.0;
  626. }
  627. }
  628. //更新屏幕
  629. [self updateScreen:_firstNum];
  630. _isWaitingForSecondNum=NO;
  631. }
  632. else{
  633. //正在输入第二个数
  634. _isTappingSecondNum=YES;
  635. if(_isNegativeNum){
  636. //_secondNum=_secondNum*10.f-1.f;
  637. if(_isTappingDecimals){
  638. _secondNum=_secondNum-5.f*_decimalRecord;
  639. _decimalRecord*=0.1;
  640. }
  641. else{
  642. _secondNum=_secondNum*10.f-5.f;
  643. }
  644. }
  645. else{
  646. //_secondNum=_secondNum*10.f+1.f;
  647. if(_isTappingDecimals){
  648. _secondNum=_secondNum+5.f*_decimalRecord;
  649. _decimalRecord*=0.1;
  650. }
  651. else{
  652. _secondNum=_secondNum*10.f+5.f;
  653. }
  654. }
  655. //更新屏幕
  656. [self updateScreen:_secondNum];
  657. _isWaitingForSecondNum=NO;
  658. }
  659. }
  660. - (IBAction)_6 {
  661. //进行下一轮的计算
  662. if(_isAfterEqual){
  663. [self AC];
  664. }
  665. if(_fistNumIsActive){
  666. //正在输入第一个数
  667. if(_isNegativeNum){
  668. if(_isTappingDecimals){
  669. //输入了小数点模式后
  670. _firstNum=_firstNum-6.0*_decimalRecord;
  671. _decimalRecord*=0.1;
  672. }
  673. else{
  674. _firstNum=_firstNum*10.0-6.0;
  675. }
  676. }
  677. else{
  678. if(_isTappingDecimals){
  679. //输入了小数点模式后
  680. _firstNum=_firstNum+6.0*_decimalRecord;
  681. _decimalRecord*=0.1;
  682. }
  683. else{
  684. _firstNum=_firstNum*10.0+6.0;
  685. }
  686. }
  687. //更新屏幕
  688. [self updateScreen:_firstNum];
  689. _isWaitingForSecondNum=NO;
  690. }
  691. else{
  692. //正在输入第二个数
  693. _isTappingSecondNum=YES;
  694. if(_isNegativeNum){
  695. //_secondNum=_secondNum*10.f-1.f;
  696. if(_isTappingDecimals){
  697. _secondNum=_secondNum-6.f*_decimalRecord;
  698. _decimalRecord*=0.1;
  699. }
  700. else{
  701. _secondNum=_secondNum*10.f-6.f;
  702. }
  703. }
  704. else{
  705. //_secondNum=_secondNum*10.f+1.f;
  706. if(_isTappingDecimals){
  707. _secondNum=_secondNum+6.f*_decimalRecord;
  708. _decimalRecord*=0.1;
  709. }
  710. else{
  711. _secondNum=_secondNum*10.f+6.f;
  712. }
  713. }
  714. //更新屏幕
  715. [self updateScreen:_secondNum];
  716. _isWaitingForSecondNum=NO;
  717. }
  718. }
  719. - (IBAction)_7 {
  720. //进行下一轮的计算
  721. if(_isAfterEqual){
  722. [self AC];
  723. }
  724. if(_fistNumIsActive){
  725. //正在输入第一个数
  726. if(_isNegativeNum){
  727. if(_isTappingDecimals){
  728. //输入了小数点模式后
  729. _firstNum=_firstNum-7.0*_decimalRecord;
  730. _decimalRecord*=0.1;
  731. }
  732. else{
  733. _firstNum=_firstNum*10.0-7.0;
  734. }
  735. }
  736. else{
  737. if(_isTappingDecimals){
  738. //输入了小数点模式后
  739. _firstNum=_firstNum+7.0*_decimalRecord;
  740. _decimalRecord*=0.1;
  741. }
  742. else{
  743. _firstNum=_firstNum*10.0+7.0;
  744. }
  745. }
  746. //更新屏幕
  747. [self updateScreen:_firstNum];
  748. _isWaitingForSecondNum=NO;
  749. }
  750. else{
  751. //正在输入第二个数
  752. _isTappingSecondNum=YES;
  753. if(_isNegativeNum){
  754. //_secondNum=_secondNum*10.f-1.f;
  755. if(_isTappingDecimals){
  756. _secondNum=_secondNum-7.f*_decimalRecord;
  757. _decimalRecord*=0.1;
  758. }
  759. else{
  760. _secondNum=_secondNum*10.f-7.f;
  761. }
  762. }
  763. else{
  764. //_secondNum=_secondNum*10.f+1.f;
  765. if(_isTappingDecimals){
  766. _secondNum=_secondNum+7.f*_decimalRecord;
  767. _decimalRecord*=0.1;
  768. }
  769. else{
  770. _secondNum=_secondNum*10.f+7.f;
  771. }
  772. }
  773. //更新屏幕
  774. [self updateScreen:_secondNum];
  775. _isWaitingForSecondNum=NO;
  776. }
  777. }
  778. - (IBAction)_8 {
  779. //进行下一轮的计算
  780. if(_isAfterEqual){
  781. [self AC];
  782. }
  783. if(_fistNumIsActive){
  784. //正在输入第一个数
  785. if(_isNegativeNum){
  786. if(_isTappingDecimals){
  787. //输入了小数点模式后
  788. _firstNum=_firstNum-8.0*_decimalRecord;
  789. _decimalRecord*=0.1;
  790. }
  791. else{
  792. _firstNum=_firstNum*10.0-8.0;
  793. }
  794. }
  795. else{
  796. if(_isTappingDecimals){
  797. //输入了小数点模式后
  798. _firstNum=_firstNum+8.0*_decimalRecord;
  799. _decimalRecord*=0.1;
  800. }
  801. else{
  802. _firstNum=_firstNum*10.0+8.0;
  803. }
  804. }
  805. //更新屏幕
  806. [self updateScreen:_firstNum];
  807. _isWaitingForSecondNum=NO;
  808. }
  809. else{
  810. //正在输入第二个数
  811. _isTappingSecondNum=YES;
  812. if(_isNegativeNum){
  813. //_secondNum=_secondNum*10.f-1.f;
  814. if(_isTappingDecimals){
  815. _secondNum=_secondNum-8.f*_decimalRecord;
  816. _decimalRecord*=0.1;
  817. }
  818. else{
  819. _secondNum=_secondNum*10.f-8.f;
  820. }
  821. }
  822. else{
  823. //_secondNum=_secondNum*10.f+1.f;
  824. if(_isTappingDecimals){
  825. _secondNum=_secondNum+8.f*_decimalRecord;
  826. _decimalRecord*=0.1;
  827. }
  828. else{
  829. _secondNum=_secondNum*10.f+8.f;
  830. }
  831. }
  832. //更新屏幕
  833. [self updateScreen:_secondNum];
  834. _isWaitingForSecondNum=NO;
  835. }
  836. }
  837. - (IBAction)_9 {
  838. //进行下一轮的计算
  839. if(_isAfterEqual){
  840. [self AC];
  841. }
  842. if(_fistNumIsActive){
  843. //正在输入第一个数
  844. if(_isNegativeNum){
  845. if(_isTappingDecimals){
  846. //输入了小数点模式后
  847. _firstNum=_firstNum-9.0*_decimalRecord;
  848. _decimalRecord*=0.1;
  849. }
  850. else{
  851. _firstNum=_firstNum*10.0-9.0;
  852. }
  853. }
  854. else{
  855. if(_isTappingDecimals){
  856. //输入了小数点模式后
  857. _firstNum=_firstNum+9.0*_decimalRecord;
  858. _decimalRecord*=0.1;
  859. }
  860. else{
  861. _firstNum=_firstNum*10.0+9.0;
  862. }
  863. }
  864. //更新屏幕
  865. [self updateScreen:_firstNum];
  866. _isWaitingForSecondNum=NO;
  867. }
  868. else{
  869. //正在输入第二个数
  870. _isTappingSecondNum=YES;
  871. if(_isNegativeNum){
  872. //_secondNum=_secondNum*10.f-1.f;
  873. if(_isTappingDecimals){
  874. _secondNum=_secondNum-9.f*_decimalRecord;
  875. _decimalRecord*=0.1;
  876. }
  877. else{
  878. _secondNum=_secondNum*10.f-9.f;
  879. }
  880. }
  881. else{
  882. //_secondNum=_secondNum*10.f+1.f;
  883. if(_isTappingDecimals){
  884. _secondNum=_secondNum+9.f*_decimalRecord;
  885. _decimalRecord*=0.1;
  886. }
  887. else{
  888. _secondNum=_secondNum*10.f+9.f;
  889. }
  890. }
  891. //更新屏幕
  892. [self updateScreen:_secondNum];
  893. _isWaitingForSecondNum=NO;
  894. }
  895. }
  896. - (IBAction)_0 {
  897. //进行下一轮的计算
  898. if(_isAfterEqual){
  899. [self AC];
  900. }
  901. if(_fistNumIsActive){
  902. //正在输入第一个数
  903. if(_isNegativeNum){
  904. if(_isTappingDecimals){
  905. //输入了小数点模式后
  906. _firstNum=_firstNum-0*_decimalRecord;
  907. _decimalRecord*=0.1;
  908. }
  909. else{
  910. _firstNum=_firstNum*10.0-0;
  911. }
  912. }
  913. else{
  914. if(_isTappingDecimals){
  915. //输入了小数点模式后
  916. _firstNum=_firstNum+0*_decimalRecord;
  917. _decimalRecord*=0.1;
  918. }
  919. else{
  920. _firstNum=_firstNum*10.0+0;
  921. }
  922. }
  923. //更新屏幕
  924. [self updateScreen:_firstNum];
  925. _isWaitingForSecondNum=NO;
  926. }
  927. else{
  928. //正在输入第二个数
  929. _isTappingSecondNum=YES;
  930. if(_isNegativeNum){
  931. //_secondNum=_secondNum*10.f-1.f;
  932. if(_isTappingDecimals){
  933. _secondNum=_secondNum-0*_decimalRecord;
  934. _decimalRecord*=0.1;
  935. }
  936. else{
  937. _secondNum=_secondNum*10.f-0;
  938. }
  939. }
  940. else{
  941. //_secondNum=_secondNum*10.f+1.f;
  942. if(_isTappingDecimals){
  943. _secondNum=_secondNum+0*_decimalRecord;
  944. _decimalRecord*=0.1;
  945. }
  946. else{
  947. _secondNum=_secondNum*10.f+0;
  948. }
  949. }
  950. //更新屏幕
  951. [self updateScreen:_secondNum];
  952. _isWaitingForSecondNum=NO;
  953. }
  954. }
  955. //小数点(与小数点“.”的Btn连接)
  956. - (IBAction)decimalPoint {
  957. //当输入完小数点再输入数字后再次输入小数点则无效
  958. if(_decimalRecord==0.1f){
  959. _isTappingDecimals=!_isTappingDecimals;
  960. }
  961. //判断当前数字是否为整数
  962. double tmp=[_result.text doubleValue];
  963. double eps = 1e-10;
  964. BOOL isInteger = tmp - floor(tmp) < eps;
  965. if(_isTappingDecimals&&isInteger){
  966. NSString*content =_result.text;
  967. NSMutableAttributedString*attributeString = [[NSMutableAttributedString alloc]initWithString:content];
  968. NSUInteger Loc = [[attributeString string] rangeOfString:@"."].location;
  969. // 需要改变的区间
  970. NSRange range = NSMakeRange(Loc, 1);
  971. // 改变小数点颜色
  972. [attributeString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];
  973. // 为label添加Attributed
  974. [_result setAttributedText:attributeString];
  975. }
  976. else{
  977. NSString*content =_result.text;
  978. NSMutableAttributedString*attributeString = [[NSMutableAttributedString alloc]initWithString:content];
  979. NSUInteger Loc = [[attributeString string] rangeOfString:@"."].location;
  980. // 需要改变的区间
  981. NSRange range = NSMakeRange(Loc, 1);
  982. // 改变小数点颜色
  983. [attributeString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:range];
  984. // 为label添加Attributed
  985. [_result setAttributedText:attributeString];
  986. }
  987. //若按完j运算符再点击小数点时,更新屏幕显示(+0或-0)
  988. if(_isWaitingForSecondNum&&_isTappingDecimals){
  989. [self updateScreen:0.0];
  990. NSString*content =_result.text;
  991. NSMutableAttributedString*attributeString = [[NSMutableAttributedString alloc]initWithString:content];
  992. NSUInteger Loc = [[attributeString string] rangeOfString:@"."].location;
  993. // 需要改变的区间
  994. NSRange range = NSMakeRange(Loc, 1);
  995. // 改变小数点颜色
  996. [attributeString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];
  997. // 为label添加Attributed
  998. [_result setAttributedText:attributeString];
  999. }
  1000. }
  1001. @end

成品图


遇到的坑

之前我将firstNum和secondNum的类型设置的是float,在一开始的调试过程中一直未出现问题,但是当写小数功能时发现了问题,当我利用nsLog打印出结果时发现:111.01+0.001的结果不等于111.011而是等于111.01098......,后来发现是因为float自身的精度问题(7位有效数字),在将float修改为double(16位有效数字)后有所改善,但遇到位数更多的小数仍会出现该问题。

关于精度的问题,我觉得这个网站讲的不错,可以参考这个网站:https://www.jianshu.com/p/9cbed21f37fe

对于需要更多精确计算的方法,也可以试试封装的NSDecimalNumber类,在这里因为没怎么用过,就不说了。

总体来说,这次设计遇到的问题主要集中在逻辑设计,需要考虑到用户的误操作(被除数为0等情况)以及数字精度问题,其他来说没有难度,可以当作IOS的初学练手。


按钮的圆形设计

我主要是通过修改按钮的layer.cornerRadius属性来实现的,这里我提供一个简单的方法,直接通过storyBoard来进行设置,如下图所示:

XCode Interface Builder开发——2的更多相关文章

  1. XCode Interface Builder开发——1

    XCode Interface Builder开发--1 创建Xcode项目 选择第二个选项 选择Single View App,点击Next 设置完后点击Next Xcode基本面板 导航面板 工具 ...

  2. ***Xcode Interface Builder或Storyboard中可建立那两种连接?

    在Xcode Interface Builder或Storyboard中,可建立到输出口(IBOutlet)和操作(方法,IBAction)的连接. IBOutlet are for output C ...

  3. IOS 使用Interface Builder开发界面入门与技巧

    引言: 通过Interface Builder(简称IB)来制作界面一直是iOS开发界饱受争议的方式.主要争议的话题是不太适合团队协作开发,再就是对IB的使用比较生疏,觉得IB只能完成一些很简单的功能 ...

  4. 苹果开发工具:Xcode和Interface Builder

    摘要:在Mac OS X上开发,首选Xcode继承开发环境.本文对开发工具套件中最重要的Xcode和Interface Builder两个工具做了简要介绍,并提供<苹果开发工具概述>PDF ...

  5. iOS开发工具Xcode:Interface Builder

    简介: Interface Builder(IB)是Mac OS X平台下用于设计和测试用户界面(GUI)的应用程序(非开源).为了生成GUI,IB并不是必需的,实际上Mac OS X下所有的用户界面 ...

  6. [转]使用 Xcode 5 和 Interface Builder创建 Hello World App

    转载地址:http://www.ithome.me/archives/581.html 使用 Xcode 5 和 Interface Builder创建 Hello World App 发表回复 当x ...

  7. iOS 8 Auto Layout界面自动布局系列2-使用Xcode的Interface Builder添加布局约束

    http://blog.csdn.net/pucker/article/details/41843511 上一篇文章<iOS 8界面自动布局系列-1>简要介绍了iOS界面布局方式的前世今生 ...

  8. 【转 iOS 8 Auto Layout界面自动布局系列2-使用Xcode的Interface Builder添加布局约束

    原文网址:http://blog.csdn.net/pucker/article/details/41843511 上一篇文章<iOS 8界面自动布局系列-1>简要介绍了iOS界面布局方式 ...

  9. 转:Cocoa、Foundation、UIKit、Objective-c、XCode、Interface Builder的概念

    Cocoa 是在Mac OS X系统上原生的一个编译环境.他包含两个框架,其实就是一系列的类库,Foundation和AppKit. 在你的iPhone等掌上设备上,使用的则是他的一个子类 - Coc ...

随机推荐

  1. CSRF与平行越权的区别

    .CSRF攻击者不需要登录,越权攻击者也得登录,只是没有做针对性的控制: .CSRF攻击者自己不访问受攻击页面,诱导受害者在登录被攻击系统后点击攻击页面:越权攻击者可以直接访问受攻击页面: .CSRF ...

  2. chcp437 转换英语,在西班牙语系统中无效

    https://social.technet.microsoft.com/Forums/en-US/9c772011-5094-4df0-bf73-7140bf91673b/chcp-command- ...

  3. lodctr /R 失败的情况

    I've resolved with the following steps: PS C:\Windows\system32> cmd Microsoft Windows [Version 6. ...

  4. Spring Cloud OpenFeign使用教程

    文章目录 Spring Cloud OpenFeign Demo 怎么配置OpenFeignServer 怎么配置OpenFeignClient 多个参数传递问题 FeignClient的日志问题 多 ...

  5. VulnHub靶场学习_HA: Chanakya

    HA-Chanakya Vulnhub靶场 下载地址:https://www.vulnhub.com/entry/ha-chanakya,395/ 背景: 摧毁王国的策划者又回来了,这次他创造了一个难 ...

  6. 汇编 之 win10 下安装dosbox 和 MASM

    所需工具链接: 链接:https://pan.baidu.com/s/1nenMsSdgEkeRKc6wh9DQRA 提取码:1r89 只需要以下两个工具 安装dosbox 和MASM步骤 (1)解压 ...

  7. 自动驾驶汽车数据不再封闭,Uber 开源新的数据可视化系统

    日前,Uber 开源了基于 web 的自动驾驶可视化系统(AVS),称该系统为自动驾驶行业带来理解和共享数据的新方式.AVS 由Uber旗下负责自动驾驶汽车研发的技术事业群(ATG)开发,目前该系统已 ...

  8. dlopen failed: empty/missing DT_HASH in "libx.so" (built with --hash-style=gnu?)

    崩溃日志内容: java.lang.UnsatisfiedLinkError: dlopen failed: empty/missing DT_HASH in "libxxxx.so&quo ...

  9. CF思维联系–CodeForces-217C C. Formurosa(这题鸽了)

    ACM思维题训练集合 The Bytelandian Institute for Biological Research (BIBR) is investigating the properties ...

  10. CodeForces - 260B

    A recently found Ancient Prophesy is believed to contain the exact Apocalypse date. The prophesy is ...