• Swift-19-基础入门


    从本章开始大概用10篇左右文章介绍下Swift语言的基本用法。

    简介

    Objective-C作为一门比较老的语言, 缺少很多现代语言所具备的高级特性。Swift是目标是比C,C++, ObjC更安全可靠,从而减少开发者对在应用运行时出错的代码进行调试的时间成本。本系列课程做为Mac OS应用开发的一个子专题,在这个专题中笔者会详细介绍下Swift程序语法。

    在同一项目中这两种语言可以同时汇编,正常情况下这两种语言可以相互调用,从Swift调用ObjectiveC时兼容性比较好,反之有些会出现一些问题,但还是不太建议在同一个项目中同时使用两种语言来开发。

    如果您对ObjectiveC非常了解的话,建议对照着来学习,这样会更容易理解,也有助于您对这两种不同语言的把控。

    目录大纲

    下面是一个拟的一个大纲,暂时不包含SwiftUI的内容。

    1. 工具和语法:工具和类型
    2. 基础知识:条件语句、数、switch、循环、字符串、空类型、
    3. 容器和函数:数组、字典、集合、函数、闭包
    4. 枚举、结构体和类:枚举、结构体和类、属性、初始化、值类型和引用类型
    5. 高级编程:协议、异常、扩展、泛型、内存管理
    6. 事件驱动的应用:Cocoa应用、IOS应用

    创建简单工程

    此专题的学习中,我们还是使用XCode工具,笔者的Xcode版本为Version 13.4.1 (13F100),不同的XCode版本的界面会有少许的变化,文中的截图可能略有差异,但应该变化不大。

    创建playground工程

    Xcode提供了下类似python语言的Jutyper Notebook功能,叫做playground,整个基础部分都会使用playground来学习。在Xcode中会有4个选项,一般选择Blank即可:
    在这里插入图片描述

    • blank:空白文档,只引入了最基础的Cocoa框架;
    • Game:引入了游戏套件,省去了从blank文档创建基础框架的过程;
    • Map:引入了地图套件,目的同Game一样;
    • Single View:引入了SwiftUI套件,学习SwiftUI时使用;

    创建好后,主界面如下:
    在这里插入图片描述
    界面非常简单,从左到右依次是:源文件浏览区、源码编辑区、运行结果区;

    import Cocoa
    
    var greeting = "Hello, playground"
    
    • 1
    • 2
    • 3

    多说一点,playground工程也不单单只是一个文件,它也是一种多文件的组合,只是对外暴露出了一个接口,打开包以后可看到它里面也包含了一系列的目录和文件:
    在这里插入图片描述

    创建Command Line Tool工程

    如果您不喜欢playground,也可以使用project的方式来练习本专题的代码,区别不大。方法是在XCode工具中选择新建Command Line Tool模板,然后按如下界面配置。
    在这里插入图片描述
    在创建工程时注意选择工程类型和编程语言,界面如下:
    在这里插入图片描述
    main.swift:程序运行主函数,默认只有两行代码

    import Foundation
    
    print("Hello, World!")
    
    • 1
    • 2
    • 3
    1. 两种工程不同的示例中的import引用不一样,这个关系不大,因为Cocoa包含了Function框架;而在基础部分我们也只会用到Function框架提供的API;
    2. 在本系列专题中笔者会使用 playground 工程来讲述Swift编程的知识,原因是可以省略好多print()函数;

    Swift语言比较恶心的一点是对于每行语句最后的 ;分号并不敏感,纯靠缩进来识别代码,做为一个老java程序员对这一点确实是习惯了好长的时间,估计是从python语言学来的吧。

    创建OSX应用

    创建一个可编辑的文本应用

    创建工程

    在这里插入图片描述

    • 开发语言选择:swift
    • UI选择:storyboards

    创建好后工程结构,默认是一种MVC架构的工程模式。
    在这里插入图片描述

    • AppDelegate.swift:入口程序
    • ViewController.swift:视图控制器,相当于Controller
    • Document.swift:相当于Model
    • Assets.xcassets:应用图标和图片资源库
    • Main.storyboard:UI图形界面,相当于View
    • Info.plist:应用设置
    • swift2cocoa.entitlements:应用发布和运行设置

    准备工作

    设计UI界面

    打开 Main.storyboard 文件。
    在这里插入图片描述

    拖动UI控件到设计面板上
    在这里插入图片描述

    设计视图控制器

    添加一个文本和两个按钮事件

    import Cocoa
    
    class ViewController: NSViewController {
    
        @IBOutlet var textView: NSTextView!
        
        @IBAction func speakButtonClicked(_ sender: NSButton){
            print("The speak button was clicked")
        }
        
        @IBAction func stopButtonClicked(_ sender: NSButton){
            print("The stop button was clicked")
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    连接控件

    方法有很多,主要是拖动,其中一种拖动方式如下图所示:
    在这里插入图片描述
    另一个拖动方式,把控件拖到controller上面
    在这里插入图片描述

    添加功能

    语音朗读

    修改Controller代码

    class ViewController: NSViewController {
    
        @IBOutlet var textView: NSTextView!
        
        let speechSynthesizer = NSSpeechSynthesizer()
        
       var contents:String?{
            get{
                return  textView.string
            }
            set{
                textView.string = newValue ?? ""
            }
        }
        
        @IBAction func speakButtonClick(_ sender:NSButton){
            if(!textView.string.isEmpty){
                speechSyntheesizer.startSpeaking(textView.string)
            }else{
                speechSyntheesizer.startSpeaking("文档是空的")
                
            }
        }
        
        @IBAction func stopButtonClicked(_ sender: NSButton){
            speechSynthesizer.stopSpeaking()
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    文档保存

    这里稍整理下代码,把M和C串起来

    Controller
    import Cocoa
    
    class ViewController: NSViewController {
    
        @IBOutlet var textView: NSTextView!
        
        var contents: String? {
            get {
                return textView.string
            }
            set {
                textView.string = newValue
            }
        }
        
        let speechSynthesizer = NSSpeechSynthesizer()
        
        @IBAction func speakButtonClicked(_ sender: NSButton){
            speechSynthesizer.startSpeaking(textView.string)
        }
        
        @IBAction func stopButtonClicked(_ sender: NSButton){
            speechSynthesizer.stopSpeaking()
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    Document
    import Cocoa
    
    class Document: NSDocument {
    
        override init() {
            super.init()
        }
        
        enum Error: Swift.Error, LocalizedError {
            case UTF8Encoding
            case UTF8Decoding
    
            var failureReason: String? {
                switch self {
                case .UTF8Encoding: return "File cannot be encoded in UTF-8."
                case .UTF8Decoding: return "File is not valid UTF-8."
                }
            }
        }
        
        //文本内容
        var contents: String = ""
    
        //自动保存功能
        override class var autosavesInPlace: Bool {
            return true
        }
    
        //创建新文档或打开旧文档时调用,负责设置NSWindowController, as!是一个类型转符,相当于强转
        override func makeWindowControllers() {
            let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
            //因为withIdentifier会返回很多不同的controller,所以这块需要强转一下
            let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController
            
            //连接controller
            let viewController = windowController.contentViewController as! ViewController
            viewController.contents = contents
            
            self.addWindowController(windowController)
        }
    
        //保存文档时调用
        override func data(ofType typeName: String) throws -> Data {
            let windowController = windowControllers[0]
            let viewController = windowController.contentViewController as! ViewController
            let contents = viewController.contents ?? ""
    
            guard let data = contents.data(using: .utf8) else {
                throw Document.Error.UTF8Encoding
            }
    
            return data
        }
    
        override func read(from data: Data, ofType typeName: String) throws {
            guard let contents = String(data: data, encoding: .utf8) else {
                throw Document.Error.UTF8Decoding
            }
            self.contents = contents
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
  • 相关阅读:
    如何用JavaScript完美地区分双击和单击事件
    TypeScript- 对于对象键名(包括函数键值)不确定的接口,可以使用字符串索引的形式
    基于C6657+国产FPGA的DSP+FPGA主控板设计方案在核电机器人的应用
    协程并发下数据汇总:除了互斥锁,还有其他方式吗?
    STM32-NUCLEO-F411RE-USART_串口
    当用get请求,接到前端传的字符串数组列表的时候,用split 分割的方式
    架构师进阶,微服务设计与治理的16条常用原则
    智慧农业新篇章:拓世法宝AI智能直播一体机助力乡村振兴与农业可持续发展
    C++ builder XE 关于intraweb TChart转换成IWimage的网页显示处理
    Guacamole Web端配置使用
  • 原文地址:https://blog.csdn.net/liudonglovehemin/article/details/137915541