从零开始的iOS开发: 20

2023-11-09

目录

一、开发环境

二、基础知识

1.往期知识点

2.简易自动布局——Stack View

三、实验步骤

 1.先在Xcode建立一个APP项目

 2.界面搭建

 3.连接控件与代码

 4.补充代码,完善功能


一、开发环境

  • 开发工具: Xcode 12.2(集成开发平台)、Simulator(模拟器,Xcode自带)
  • 开发语言: Swift 5
  • 界面搭建: Storyboard(故事板)

二、基础知识

1.往期知识点

00 | Swift基础语法(上)

01 | Swift基础语法(下)

10 | 如何构建一个APP

2.简易自动布局——Stack View

        Stack View(堆栈视图)类似于HTML的盒模型,你可以把它理解为一个容器。我们可以利用Stack View在水平(或垂直)方向堆叠多个子视图。

        一个Stack View可以用来封装各种UI控件以及其他Stack View,通过添加对Stack View的约束(设置该View到父View的距离)可以实现UI控件的定位和布局。

 1)添加Stack View

 2)添加约束

 3)查看约束

 4)设置Stack View的属性

三、实验步骤

        在MVC架构下,用故事板来开发一个简易计算器APP需要以下步骤:

  • 搭建界面——添加必要的UI控件,并实现UI控件的自动布局
  • 连接UI控件与代码
  • 不断完善代码,实现需求的功能

        应用界面的设计如下,要求计算器至少能实现整数和浮点数的加减乘除运算。


 1.先在Xcode建立一个APP项目

 

 2.界面搭建

 1)打开Main.storyboard主故事板

同时,模拟器和View视图统一选择iPhone 8 Plus

 2)先添加一个Button(按钮)控件

 通过Inspector设置Button的属性

将Button显示的文字“Button”修改为“1”,文字大小Font设置为30,文字颜色Text Color暂不修改

 

 将Button的背景颜色Background修改为Yellow(或其他你喜欢的颜色)

 修改Button的宽和高为50

 3)添加容器

方法是按住鼠标左键框选要放入容器里的控件,完成后点击左下角的Stack View

可以看到Button1已经被放入Stack View里了:

 

 4)批量添加Button(包括它外面的容器)

         一个比较快捷的方法是,框选你要复制的控件,然后按住option键往旁边拖拽

         如果不清楚这个方法,一个Button一个容器地添加也可以,就是没上面的方法快。

 5)为一行的Button添加容器

框选+Stack View

 6) 继续往下添加Button

        我们继续往下复制,总共需要4*5个Button。依然使用框选+按住option+拖拽的方法

 7)把所有Button封装进一个容器

 8)在顶部添加一个Lable(标签)控件

 同时,也将Lable封装进一个Stack View

 9)将Lable和Button都封装进一个容器中

 

        到了这一步,所有的控件和容器都以添加完成。接下来要做的就是为各个容器添加约束,实现自动布局。

 10)为最外层的Stack View设置约束

        添加4条约束:将其上下左右四个方向的距离设置为0

 

  11)设置包含所有Button的Stack View

        这一步是实现自动约束的关键步骤,在左侧的Documen Outline中选择包含所有Button的Stack View,设置Stack View的属性

Alignment 设置为Fill,Distribution设置为Fill Equally,Spacing设置为10

 

 12)为每一行的Button添加约束

        添加2个约束:左右距离为0

 完成后结果如下:

显然,我们需要设置包含一行Button的Stack View的属性

 13)设置包含一行Button的Stack View的属性

Alignment 设置为Fill,Distribution设置为Fill Equally,Spacing设置为10

        将所有包含一行Button的Stack View的属性Alignment 设置为Fill,Distribution设置为Fill Equally,Spacing设置为10

 14)设置Lable的高

 

 15)修饰背景和UI控件

将Lable的文字设置为0,颜色Color设置为白色,文字大小Font设置为50

在Documen Outline中选择最外层的Stack View,将背景颜色Background设置为黑色

修改Lable文字的对齐方式(改为右对齐)

修改各个Button的文字

 iOS支持特殊符号(例如π对应快捷键option+P,平方根对应快捷键option+V)

 

修改Button的文字颜色和背景颜色

完成后:

到了这一步,页面的搭建就已经完成了,可以试运行一下,看看有没有bug。

 3.连接控件与代码

添加一个新的窗口,同时打开主故事板和ViewController.swift页面

 由于这里不需要viewDidLoad函数,直接删掉

连接控件与代码,方法是选中控件,按住Ctrl+拖拽

将Lable连接到代码区:

将某个Button连接到代码区:

接着把所有Button都连接到touch代码块 

通过鼠标悬停在代码区左侧的实心圆点上,可以查看连接的情况:

删除连接、重建连接请参考10 | 如何构建一个APP 的结尾部分

将所有控件与代码连接完可以试运行一下,看连接有无错误

 4.补充代码,完善功能

 1)添加代码,实现Lable的数字显示功能

试运行一下,我们发现,每按一个数字键,之前的数字就被覆盖掉了,没办法显示2位及以上的数值。为了解决这个问题,我们采用下面的代码:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var display: UILabel!
    
    @IBAction func touch(_ sender: UIButton) {
        let digit = sender.currentTitle!    //获取按钮值
        let textInDisplay = display.text!   //获取标签值
                
        if let mathematicalSymbol = sender.currentTitle {
            switch mathematicalSymbol {
                case "0","1","2","3","4","5","6","7","8","9":
                    if textInDisplay != "0" {
                        display.text = textInDisplay + digit
                    } else {
                        display.text = digit
                    }
                default:
                    break
            }
        }
    }
    

}

通过Lable标签原来显示的数值textInDisplay与数字键代表的数值digit的拼接,实现了多位数字的显示。

2)继续完善代码

//
//  ViewController.swift
//  Calculator
//
//  Created by Apple on 2021/12/5.
//

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var display: UILabel!
    
    var num1: Double?   //操作数1
    var num2: Double?   //操作数2
    var ope: String?    //运算符
    var IsFloat = false //浮点运算标志位
    var displayValue : Double {
        get{
            return Double(display.text!)!
        }
        set{
            display.text = String(newValue)
        }
    }
    
    @IBAction func touch(_ sender: UIButton) {
        let digit = sender.currentTitle!    //获取按钮值
        let textInDisplay = display.text!   //获取标签值
                
        if let mathematicalSymbol = sender.currentTitle {
            switch mathematicalSymbol {
                case "0","1","2","3","4","5","6","7","8","9":
                    if textInDisplay != "0" {
                        display.text = textInDisplay + digit
                    } else {
                        display.text = digit
                    }
                case "AC": display.text = "0"
                case "π": display.text = String(Double.pi)
                case "√": display.text = String(sqrt(displayValue))
                case "sin": display.text = String(sin(displayValue))
                case "+","-","*","/":
                    if textInDisplay.contains(".") {
                        IsFloat = true
                    }
                    self.ope = mathematicalSymbol   //记录运算符
                    self.num1 = displayValue        //记录操作数1
                    display.text = "0"              //清空计算器显示
                case "=":
                    if textInDisplay.contains(".") {
                        IsFloat = true
                    }
                    self.num2 = displayValue
                    display.text = calculation(num1: num1, num2: num2, ope: ope, IsFloat: IsFloat)
                    IsFloat = false
                    case ".":
                        if textInDisplay != "0" {
                            display.text = textInDisplay + digit
                        } else {
                            display.text = "0."
                        }
                    default:
                        break
            }
        }
    }
    
    //calculation:执行计算操作
    func calculation(num1: Double?, num2: Double?, ope: String?, IsFloat: Bool) -> String {
        if ope == nil {
            return "EOF"
        }
        if num1 == nil || num2 == nil {
            return "0"
        }
        var result: Double
        switch ope {
            case "+": result = num1! + num2!
            case "-": result = num1! - num2!
            case "*": result = num1! * num2!
            case "/":
                if(num1 != 0) {
                    result = num1! / num2!
                }
                else {
                    return "EOF"
                }
            default:
                return "EOF"
        }
        if IsFloat {
            return String(Float(result))
        } else {
            return String(Int(result))
        }
    }

    
}

         不建议将整块代码直接负责到项目中,因为这有可能影响原来的(控件与代码的)连接。要么只复制代码中方法的实现部分;要么删除所有连接,重新连接控件与代码。

 3)运行

 

 

        如果发现模拟器旋转之后,APP的页面没有跟着旋转(没有变成横屏显示),那么可能是APP的配置文件关闭了旋转功能。下面介绍解决办法:

        确保勾选了Landscape LeftLandscape Right

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从零开始的iOS开发: 20 的相关文章

  • Cocos2D复杂动画[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在使用 Cocos2D 将我的游戏从 Flash 移植到 iOS 我现在有一个工作版本 我很高兴我
  • 在其他数组中使用 ForEach 的索引

    为什么我不能使用 FromEach 的索引作为其他数组的索引 这个索引是Int 那么有什么问题呢 var word String return slova selector var symbols Array
  • 使用 Swift 将自定义字体添加到 macOS 应用程序

    我遵循了一堆教程 但它不起作用 我只是想向 macOS 应用程序添加自定义字体 我基本上尝试过 添加了 ttf字体文件到我的项目 目标会员资格已设置 我还确保使用复制文件Copy Files within Bundle Phases 编译后
  • 我如何在 viewDidLoad 中执行 UIView animateWithDuration ? IOS 7

    我在 viewDidAppear 中尝试这个 但我有一秒钟的延迟 我能做什么 在 viewDidLoad 中工作 void viewDidAppear BOOL animated fullRotation CABasicAnimation
  • 根据一个属性对数组进行排序[重复]

    这个问题在这里已经有答案了 我有一个名为 NSMutableArrayallItems其中有以下内容ProductData目的 每个对象都有cid cname ctype and cimage 正如您在下面看到的 json 对象没有按顺序出
  • 什么是已弃用的推送转场? (iOS 8)[重复]

    这个问题在这里已经有答案了 我不知道在这种情况下已弃用意味着什么 我是编程新手 正在 Xcode 6 中制作我的前几个应用程序 今天我正在制作一个待办事项列表应用程序 当连接到用户可以输入新待办事项以添加到主表的场景时 我被邀请使用推送转场
  • 如何在 UIAlertView (iOS) 中的其他两个按钮(堆叠)之间添加取消按钮

    我正在尝试创建一个带有三个按钮 将堆叠 的 UIAlertView 我希望 取消 按钮位于其他两个按钮之间的中间 我尝试将 cancelButtonIndex 设置为 1 但如果还有其他两个按钮 它只会将它们放置在索引 0 和 1 处 我知
  • 在视图控制器中获取 applicationDidFinishLaunching 调用。解析尚未初始化

    我正在尝试从 Parse 加载数据Initial View 控制器 问题是 Parse 在我的中初始化AppDelegate s didFinishLaunching所以我需要等到它被调用后再尝试从 Parse 加载数据 在我的视图控制器中
  • iOS 自定义滑块删除两端的最小和最大空间

    我正在尝试使用自定义滑块 class MySlider UISlider override func trackRect forBounds bounds CGRect gt CGRect let customBounds CGRect o
  • 在 Swift 中对约束进行动画处理

    我有一个UITextField我想在点击时放大它的宽度 我设置了约束 并确保左侧约束的优先级低于我尝试在右侧设置动画的约束 这是我尝试使用的代码 move the input box UIView animateWithDuration 1
  • 如何以编程方式设置设备(UI)方向?

    希望屏幕 UI 上的所有内容都能够从横向左向右旋转 反之亦然 我该怎么做呢 这是私人的吗 我知道 BOOL shouldAutorotateToInterfaceOrientation UIInterfaceOrientation inte
  • NSCalendar 返回明年第一周上周一的错误日期

    我使用下面的代码使用随机日期来计算上周一 哪个工作文件但我的代码在明年日期中断 下面是相同的代码 NSDate date NSDate dateWithTimeIntervalSince1970 1483620311 228 NSLog c
  • 删除 Xcode 项目的源代码控制

    我在 Xcode 项目上使用源代码控制已经有一段时间了 但现在我不想使用源代码控制 如何从 Xcode 中的项目中删除源代码控制 有三种方法 方法 1 将禁用所有项目的源代码管理 方法 2 将删除所有项目的单个存储库的链接 方法 3 将删除
  • 使用远程图像创建 MSSticker

    我正在尝试找出使用网络上托管的图像创建 MSStickers 的方法 我可以使用本地图像创建 MSStickers 例如 NSString imagePath NSBundle mainBundle pathForResource imag
  • 使用 Protobuf-net,我收到有关 List 未知线路类型的异常

    我已经开始将 Unity iOS 游戏转换为使用 Protobuf net 保存状态 看起来一切正常 直到我将此实例变量添加到GameState ProtoMember 10 public List
  • 无法从 iOS 中的框架访问 .nib(XIB) 文件

    我已经从现有的代码库中创建了一个框架 并尝试在新的代码库中使用它 这很好用 但是当我尝试访问属于我的框架包的一部分的 nib 文件时 我的应用程序崩溃了 这是我用来访问视图控制器 XIB 文件的代码 testViewController c
  • 如何将图像放入此 UIPickerView 中?

    我不知道如何创建一个在文本一侧带有图像的自定义 UIPickerView 我一直在寻找一种方法 我刚刚发现了这个 UIView pickerView UIPickerView pickerView viewForRow NSInteger
  • 如何正确创建迦太基 cartfile?

    我正在研究购物车文件 迫不及待地想 简单地创建一个购物车文件 就像所有说明所说的那样 只是 如何 简单地 创建一个 Cartfile 我创建了一个纯文本文档 将其命名为 cartfile 并在其中复制了一些依赖项 Ran carthage
  • Swift 运行时库与 Swift 标准库

    In this 关于如何使用 CocoaPods 的教程 https www raywenderlich com 97014 use cocoapods with swift我无法理解以下段落 与 Objective C 不同 标准 Swi
  • 核心数据:重命名属性,而不会导致用户及其当前数据出现问题

    我只想为我的应用程序的新版本重命名并在表上添加属性 并且如果应用程序已安装 我想保留数据 首先我只是设置选项 let options NSMigratePersistentStoresAutomaticallyOption true NSI

随机推荐

  • 【深度学习】CV_基于CNN的图像分类模型_代码逐行注释解析

    目录 前言 一 任务描述和关键环节 一 数据预处理 二 网络模块设置 三 网络模型保存与测试 二 具体步骤 一 任务分析与图像数据处理 1 导包 2 数据读取与预处理 2 1 数据读取 2 2 数据预处理 1 制作数据源 2 将预处理的数据
  • Nuxt3请求封装数据封装

    新建utils http ts import hash from ohash 后端返回的数据类型 export interface ResOptions
  • 重磅!Cloud Ace 在巴西圣保罗建立第一家南美子公司

    Cloud Ace Inc 总部 东京都千代田区 代表 青木诚 以下简称 Cloud Ace 于2023年3月10日宣布在巴西成立新子公司 Cloud Ace 一直在全球扩展其业务 从亚洲开始 目标是在世界各地设有办事处 我们最近加入的是在
  • Web菜鸟入门教程 - MyBatis通过数据库生成java代码

    SpringBoot大大简化了Web开发流程 可以这么说 做Web后来开发大部分时间就是在做配置文件修改 Web开发中 终端的运算能力越来越强 大部分场景就是数据库的操作 只有少部分逻辑会放在Web端处理 而这些增删查改基本属于标准的格式
  • 实现一个顺序存储的线性表(数据结构与算法 - 线性表)

    任务描述 本关任务 实现 step1 Seqlist cpp 中的SL InsAt SL DelAt和SL DelValue三个操作函数 以实现线性表中数据的插入 删除与查找等功能 相关知识 线性表是最基本 最简单 也是最常用的一种数据结构
  • Python list函数

    目录 描述 语法 使用示例 1 创建一个空列表 无参调用list函数 2 将字符串转换为列表 3 将元组转换为列表 4 将字典转换为列表 5 将集合转换为列表 6 将其他可迭代序列转化为列表 注意事项 1 参数必须是可迭代序列对象 将列表转
  • chrome中直接使用import

    现在我们在开发项目时都是基于构建工具 像webpack 上进行开发 所以在使用import时得心应手 但今天在chrome中直接使用import时 发现不知道如何使用 chrome中直接使用import 三个条件 浏览器版本需要支持 浏览器
  • c++常用输出函数详解

    1 printf printf的基本运用 printf是c 标准输出函数 目的是向标准输出设备按规定格式输出信息 格式如下 printf d a 上面的a是一个int形变量 但如果想输出一个字符型的变量 字符串等该怎么办呢 那我们就要把 后
  • 【mmdetection】小trick试验结果

    基准 faster rcnn r50 fpn 1x coco简称frrf config mAP 最好 模型大小 publish model cal train time s iter 1 frrf 0 9346 315 32MB
  • axios实现同步请求

    如何实现ajax请求的同步 通过jquery发送 将async属性设置为false 这样就会发送同步请求 在axios中 所有的请求都是异步发送的 所以单独用axios是实现不了同步的 需要结合async与await关键字使用 var da
  • ab压力测试 和 nginx 配置优化 及 用户打开的最大进程数

    原文 https blog csdn net wudinaniya article details 86064797 一 ab压力测试 和 nginx 配置优化 压力测试工具 ApacheBench 简称ab 是Apache 中自带的基准性
  • 毕业设计-基于 Python 的天气预测系统

    目录 前言 课题背景和意义 实现技术思路 一 Python 二 网络爬虫 三 基于 Python 的天气预测系统 四 系统测试 五 总结 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学
  • MATLAB 创建矩阵

    创建简单数值矩阵 输入矩阵是要以 为标识 矩阵的元素应在 内部 此时MATLAB才识别为矩阵 矩阵的同行元素之间可由空格或 分隔 行与行之间要用 或回车符分隔 A 1 2 3 4 5 6 7 8 9 运算结果 使用 zeros 函数和 on
  • luci流程简介

    LuCI作为 FFLuCI 诞生于2008年3月份 目的是为OpenWrt固件从Whiterussian 到 Kamikaze实现快速配置接口 LuCI是OpenWrt上的Web管理界面 LuCI采用了MVC三层架构 使用lua脚本开发 所
  • mysql不能使用别名做判断条件的解决方案

    错误例子 select name as n from user where n 张三 报错 n 字段在表user中不存在 解决办法 select name as n from user where name 张三 具体原因 请自行百度
  • SpringMVC框架从入门到精通

    文章目录 SpringMVC 框架介绍 概述 MVC模型 性能超群 工作原理 案例 展示汽车数据 需求 创建Maven module 创建RunApp java Car java CarController java 测试 处理请求参数 概
  • element-ui表格组件el-table实现行编辑与新增功能

    element前端ui组件挺美观的 我们也使用了他们的table组件 但是默认没有提供行编辑功能 我们可以通过将table的每个单元格换成input框来巧妙实现 默认每个单元格就是一个template数据填充 不可编辑 我们可以在templ
  • Qt-Web混合开发-QtWebChannel实现Qt与Web通信交互(4)

    Qt Web混合开发 QtWebChannel实现Qt与Web通信交互 文章目录 Qt Web混合开发 QtWebChannel实现Qt与Web通信交互 1 概述 2 实现效果 3 实现功能 4 关键代码 5 源代码 更多精彩内容 个人内容
  • 不仅仅好看!30个优秀logo的设计思想分析

    拥有一个抢眼的Logo对企业来乃一大幸事 毕竟Logo千千万 但真正让人过目不忘的作品可是屈指可数 好的Logo必须量体裁衣 迅速传递出企业的价值和理念 本文里精选了30个经典的标志设计 并附上设计思想分析 相信会对你受益匪浅 Castle
  • 从零开始的iOS开发: 20

    目录 一 开发环境 二 基础知识 1 往期知识点 2 简易自动布局 Stack View 三 实验步骤 1 先在Xcode建立一个APP项目 2 界面搭建 3 连接控件与代码 4 补充代码 完善功能 一 开发环境 开发工具 Xcode 12