修炼 SwiftUI:Swift Project 01 - Part 1

Project 1

项目内容:

生成一个应用程序,允许用户滚动图像列表,然后选择要查看的图像。

Part 1

对应网页教程的 Day 16。

1. 创建项目

在 XCode 的 File 菜单上选择 New ,在展开菜单中选择 Project...,或者直接按Shift+Command+N ,会弹出新建项目对话框。

XCode 提供了针对不同系统的很多模板,随着苹果公司将操作系统细分为各种 xOS,加上 Swift 和 XCode 的升级,网页上的模板显然和我使用的不大一样,原先的 Single View Application 米有了,现在都称为 App。选中模板后的对话框用来设定项目的基本信息。

  • Project Name : 项目名称,随便写,不过不建议有空格,最好使用驼峰命名法。
  • Team :None代表你单枪匹马,Team表示你有团队,自己学习的时候没啥用。
  • Organization identifier :组织标识,一般是域名倒着写。但是这玩意儿有点坑,总是出现一个编译警告,说你这个无法验证。网上很多人说了不少方法回避这个,我暂时没理他。
  • Interface :两个选项,SwiftUIStoryboard,目前网上的大多数教程使用前者的比较多,虽然 Apple 公司的开发者大会上关于 Storyboard 的演讲越来越多。
  • Life Cycle :两个选项,SwiftUI AppUIKit App Delegate 。如果 Interface 选中的是 Storyboard,那么就只能是后者。
  • Language :两个选项,SwiftObjective-C,后者只有在 Interface 为 Storyboard,且 Life Cycle 为 UIKit App Delegate 时才可以选择。应该是给以前的项目留的兼容。

万事开头难 。第一个项目就遇到了麻烦。可能是因为 XCode 的更新,也可能是因为 Swift 的更新,反正现在新建项目的选项和网页上的教程基本上对不上。经过对新建项目时几个选项的反复试验和对 GitHub 上项目源码的研读,终于知道了网页上的项目创建时所使用的参数。

看上去这个项目使用了 Storyboard,创建时 Interface 要选 Storyboard,Life Cycle 自动会选择为UIKit App Delegate。Swift 教程的其他项目等后面做到时再看看。

而 SwiftUI 教程中似乎没有使用 Storyboard,创建时 Interface 要选 SwiftUI,Life Cycle 要选择为 UIKit App Delegate

第三种情况是 Interface 选 SwiftUI,Life Cycle 要选择为 SwiftUI App。这个回头需要自己研究一下。

搞清楚了这些就动手干吧!

2. 复制文件

因为要让用户浏览图片,所以我先去视觉中国下载了一些免费图片。将图片文件夹拖拽到项目中,在对话框里面勾选 Copy Items if needed,并选中 Create groups (这个很重要!!)

3. 修改视图控制器

ViewController 是用来控制所有需要在屏幕上显示的视图的控制器。

3.1 代码

ViewController.swift

//
//  ViewController.swift
//  Project01
//
//  Created by Howard Ge on 2021/9/15.
//

import UIKit

class ViewController: UIViewController {
    
    var pictures = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let fm = FileManager.default
        let path = Bundle.main.resourcePath!
        let items = try! fm.contentsOfDirectory(atPath: path)
        
        for item in items {
            if item.hasPrefix("food") {
                // load picture
                pictures.append(item)
            }
        }
        print(pictures)
    }
}
3.2 代码说明
行号说明
10ViewController 为视图控制器,应该是用来控制所有需要显示的视图的。默认情况下,该类继承 UIViewController 类,
12为要加载的图片定义数组定义属性 pictures,目的是系统启动加载 viewDidLoad 之后仍能保存图片名称列表
14覆写 viewDidLoad 方法
15默认只有这一行代码,调用父类的 viewDidLoad 方法。这个是不能省略的
17定义 FileManager 实例,保存到 fm 中。
18通过 fm 的 resourcePath 方法 获取保存图片的路径,保存到 path 中。
19通过 FileManager 的 contentsOfDirectory 方法,以 path 为参数,获取到 图片名称 列表,保存到 items 中。
21遍历 items,将图片名称添加到 pictures 数组
27在控制台打印 pictures 数组
3.3 运行结果
["food08.jpg", "food09.jpg", "food07.jpg", "food06.jpg", "food12.jpg", "food04.jpg", "food10.jpg", "food11.jpg", "food05.jpg", "food01.jpg", "food02.jpg", "food03.jpg"]

可以看到,已经成功地保存了文件信息。

3.4 补充了解

代码中第 8 行的引入,说明编程是围绕 UIKit 开展的。UIkit 是Swift 开发的另一个框架。这表示这里侧重练习的是 Swift 语言本身,而非 SwiftUI 框架。基于此,大叔不对相关语言中应用到的类和方法进行更多的讨论。大家可以通过Shift+Command+0打开帮助自己研究。也可以 Option+鼠标左键 点击要了解的类或者方法。

参考网址:

Apple Documentation Archive 是以前的 Apple 官方文档站点,可以查到很多内容,比如要了解 UIKit 中关于 View Controller 的内容(View Controller Programming Guide for iOS)。但现在不再更新了,由此可以看出来,苹果已经把所有的重点都放在了 SwiftUI 框架上。而且新的Apple Developer 站点 中也非常醒目地给 SwiftUI 留了个位置,新的官方文档站点 只是保留了以前文档站点的入口。

4. 界面实现

首先,将 ViewController 继承的类从 UIViewController 换成 UITableViewController,一个更善于处理表格数据的 UIViewController 子类。修改了以后,如果运行程序会报错:

libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UITableViewController loadView] instantiated view controller with identifier "UIViewController-BYZ-38-t0r" from storyboard "Main", but didn't get a UITableView.'
terminating with uncaught exception of type NSException

意思是在名为 Main 的 Storyboard 上没有找到 UITableView。所以要修改界面来匹配 ViewController。实现的方式可以直接编写代码,也可以使用图形编辑器——Interface Builder(简称 IB)。

现在到屏幕左侧的项目导航中(Command+1)找到并单击 Main.storyboard 这个文件。可以在主编辑区看到整个 Storyboard,这里包括了所有的界面。在这里可以进行可视化编辑。

4.1 搭建基础页面
  1. 选中 View Controller Scene,按 Backspace 删除
  2. Shift+Command+L 打开 Object Library 对话框,通过滚动或者搜索找到 Table View Controller,拖拽到 Storyboard 上。
  3. Option+Command+4 打开 identity inspector ,将 Class 选为 ViewController,这样就和上面的代码关联好了。
  4. Option+Command+5 打开 attributes inspector ,选中 Is Initial View Controller,表示这里是程序入口。
  5. 在主编辑区左侧的大纲结构中,选中 Table View 中的 Table View Cell,然后在 attributes inspector 中的 Identifier 中输入 Picture,并将 Style option 从 Custom 更改为 Basic。
  6. Editor 菜单中选择 Embed In > Navigation Controller。这时会在主编辑区添加一个新的视图,原有的视图会右移,同时入口的箭头指向了新的视图。

Command+R 运行程序后,可以看到空白的表格和顶部灰色背景的空白导航栏。

4.2 向空白表格添加内容

一共需要做两件事:1. 表格一共需要展示的行数;2. 每一行需要展示的内容。这些可以通过覆写两个 tableView 函数来完成。

在 viewDidLoad() 函数的后面(就是这个函数的最后一个花括号的下一行)添加下面的代码:用来确定行数。

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return pictures.count
}

现在,再来覆写另一个 tableView 函数,用来确定每行的内容。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Picture", for: indexPath)
    cell.textLabel?.text = pictures[indexPath.row]
    return cell
}
行号说明
1_ 表示该参数调用时可以隐含参数名
2dequeueReusableCell 函数可以理解为解析表格单元格内容。
withIdentifier 参数:指明要解析的单元格标志,要与在视图设计中的 Table View Cell 的 Identifier 一致
indexPath 参数:包含 section 和 row 两个信息。本例仅涉及 row。(第 3 行可以看见具体调用)
3cell 的类型是 UITableViewCell,包含了一个可选属性 textLabel。

Command+R 运行程序后,可以看到每行展示的是文件名。可以尝试在返回前加上 print(cell) 在控制台打印单元格 cell 的内容。

大叔的心得

第一阶段的工作告一段落了,梳理一下涉及的内容:

  • 创建项目时,不同的模板和选项会产生不同的项目结构。
  • 复制文件到项目的时候别忘记了选中 Create groups
  • ViewController 类所继承的类要与视图中的组件相匹配,否则会报错。
  • 用属性记录需要在页面加载后保存的数据。Pictures
  • 覆写两个 tableView 函数来返回表格行数和单元格内容。
  • Table View 中 Table View Cell 的标志要与覆写的 tableView 函数中需要的 withIdentifier 的值一致,否则无法匹配。

我大概花了差不多一周的时间,简单复习了一下 Swift 语言的基础,对比了一下两个课程的差异,确定了学习的思路。

[注] 这里使用的快捷键和菜单可能因为 XCode 的版本不同而与你的略有差异,耐心到菜单中去找一下就好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值