欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Swift入门[基于Java基础]

程序员文章站 2024-02-20 19:01:52
...

Swift入门

学习目标

由于已经有了Java编程思想,所以着重了解Swift语言特有的特性,与Java不一样的地方。最终目的是可以使用Swift语言开发iOS应用。

学习过程

  • [阅读苹果官网Swift文档](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html)
  • 使用Xcode动手尝试运行部分代码。
  • 文档总结

学习内容

The Basics [Swift概览]
  • Swfit是类型安全的语言。变量的类型是确定的。不同于PHP,PHP类型是不确定的。
  • Swift结束不用添加分号;,这点与Java不同。
  • 数据类型。Swift的基础数据类型有表示整型的Int,表示浮点型的Double和Float,表示布尔值的Bool,表示字符串的String。集合类型有标识数组的Array,表示无序集合的Set,表示映射关系的Dictionary。Swfit还提供自己特有的类型:元组.元组没有具体的关键字,表达形式是(value1,valule2...);

  • 声明方式。Swift的声明方式只有两种,通过关键字 let和var。这点区别与Java的变量声明。let声明的变量类似于Java通过final声明的变量,不可修改。var声明的变量可以被修改。声明的变量,使用前必须初始化(可选类型除外)。下面是变量max的几种声明方式:
    let max = 10; //明确了 max的类型是Int. let max :Int ://同样明确了max的类型是Int.因为这里没有确定初始值,所以使用前必须赋值,否则会报错。 var max = 10//max可以改变成其他值,而let声明的就不可以。
  • 在字符串中连接变量值可以通过 (变量名称)方式。例如
    let name = "Zhouztashin"; NSLog("my name is \(name)");
  • Int类型区分。Swift语言,Int类型同样有有符号和无符号的区分和位数的区分。一般,我们使用Int就可以了,当前平台是32位,它就是32(Int32)的。无符号的Int类型U开头,例如UInt32。
  • Double表示64位的浮点数,Float表示32位的浮点数。
  • 类型别名。Swift提供类型别名的机制,提高代码可阅读性。使用关键字 typealias可以为类型指定别名:
    typealias AudioSample= UInt16;//为UInt16指定别名。
  • 可选概念。Swfit里面有一个"Optionals"概念。例如某个变量可以有值,也可以没有值。这就是可选的概念。没有值使用nil表示。使用?符号声明的变量就是可选变量,可选变量可以被赋值为nil。非可选变量不能为nil。
  • 可选概念使用方式。Swfit提供了一种可选概念的使用方式:
    //语法 if let 变量名 = 可选语句{ //如果赋值最终不等于nil 则执行这里的语句 }else{ //赋值等于nil ,则执行这里。 }
    //例子 //强制转换 字符串 "not Number"为Int,结果是失败,所以number =nil; if let number = Int("not Number"){ //由于number=nil,所以这里不会被执行 }
  • Swfit也提供了异常处理机制,类似于Java的异常处理机制。

Basic Operators [Swfit 操作符]
  • 各类操作符与Java是一致的。
  • 操作符号的左右两边要留出空格,不然会报错。
  • nil值操作符。Swfit提供了??操作符。
    let valueA = "A"; var valueB: String? var result = valueB ?? valueA; //如果valueB 为nil,那么就将valueA的值给result.
  • 范围操作符。Swfit提供范围操作符号"a...b".指定了 从a到b。
    for index in 1...5{ //这里循环5次,从1到5。 }
  • 半开范围操作符。Swift提供了半开操作符 "a..<b",类似于范围操作符。
    for index in 0..<10{ //循环10次,从0到9. }
Strings and Characters [字符和字符串]
  • 字符串声明方式。
    var emptySting = ""; var anotherEmptyString = String();
  • 字符声明方式。
    let singleChar : Character;
  • 字符串是值类型。不是引用类型。这一点需要与Java区分。
  • 字符串拼接。字符串拼接可以通过"+";
  • 可以通过 (变量)方法在字符串里面嵌入变量值。例如
    let name = "Zhouztashin"; print("My name is \(name)");//会打印出 My name is Zhouztashin。
  • Swift提供了判断是否有相同前后缀的功能。例如。
    let str1 = "LiXX"; let str2 = "ssLi";
  • Swfit提供了Unicode的访问形式。"\u{代号}"
  • 常用方法。
    var name = "Zhouztashin"; 1、name.isEmpty //空判断 2、for character in name.characters{//遍历打印字符 print(character);//打印单个字符 } 3、name.count;//获取字符串数量 4、name[index];//获取某个下标位置的字符 5、name.insert("My name is",at :0);//在下标0的位置插入字符串。 6、name.remove(at :0);//移除下标为0的字符。 7、name.hasPrefix("Zhou") // 前缀判断,因为有前缀Zhou,所以结果为true; 8、name.hasSuffic("shin")//因为有后缀shin,所以结果为true;
Collection Types [集合]
  • 集合数据类型。Swift提供了三种集合的数据类型。Array,Set,Dictionary。其中Array类比于Java的列表和数组,Set类比Java的Set,Dictionary类比Java的Map。
  • 集合可变与不可变。不同于Java语言,因为Swift集合类型是值类型,所以,Swfif的集合类型如果被声明为let的话,该集合本身和其包括的数据均不能变动。
  • 集合元素访问&赋值方式。Array可以通过数字下标方式访问和赋值,Set则需要通过特定的SetIndex<>下标访问。Dictionary可以通过Key以下标的方式访问相应值。
  • 集合通用方法。空判断(isEmpty)和获取数量(count)的方法是通用的。
  • Array声明方式:
    var someInts :Array<Int>;//声明一个未初始化的Int 列表类型。 var someInts :[Int];//简约声明方式。 var someInts = [Int]();//简约初始化空方式。 var someInts = [];//当someInts已声明了具体类型,那么可以通过[]将该列表置为空 var someInts = [12,23];//简约初始化赋值方式。 var threeDoubles = Array(repeating :0,0,count:3);//特定声明方式,结果会生成 [0,0,0,0,0,0];
  • Array常用方法。与第2节字符串操作所用的方法是一样的。
  • Array遍历方式:
    var someInts = [1,2,3]; 1)、遍历元素 for item in someInts{ print(item);//打印1,2,3 } 2)、遍历下标和元素 for (index, value) in someInts.enumerated(){ print("\(index) AND \(value)"); }
  • Set声明方式:
    var someInts :Set<Int>;//声明一个未初始化的Int 列表类型。 var someInts :Set = [Int]();//简约初始化空方式。 var someInts = [];//当someInts已声明了具体类型,那么可以通过[]将该列表置为空 var someInts :Set = [12,23];//简约初始化赋值方式。
  • Set常用方法。与第2节字符串操作所用的方法是一样的。
  • Set遍历方式。与Array类似。
  • Dictionary声明方式:
    var someDictionary = String : String;//声明一个字符串与字符串的映射字典。
    var someDictionary :[String : String];
    var someDictionary = ["Zhou":"ZeXuan","Zhong":"Hong"];//以:符号分割键值对。
    var simeDictionary = [:];//将该字典变量置为空。
  • Dictionary常用方法:

    var someDictionary = ["Zhou":"ZeXuan","Zhong":"Hong"];
    1)、更新键值对。[也可以通过下标方式]
    someDictionary.updateValue("Yong",forKey:"Zhong");//更新键为Zhong的值为 "Yong";
    2)、移除键值对。
    someDictionary.removeValue(forKey:"Zhong");//移除键为Zhong的键值对。
  • Dictionary 遍历方式:
    var someDictionary = ["Zhou":"ZeXuan","Zhong":"Hong"]; //遍历获取键值对 for (key,value) in someDictionary{ print("\(key),\(value)");//打印出 Zhou,ZeXuan。Zhong,Hong。 } //遍历键。 for key in somDictionary.keys{ print(key);//打印键。 } //遍历值 for value in someDictionary.values{ print(value);//打印值 }
  • 获取键值对列表。通过 let keys = [String] ta(someDictionary.keys) 获取键列表。值也一样,不过把调用的方法从keys改为values。

Control Flow [控制流程]
  • Swift提供了的判断流程、循环流程,选择流程。这里仅列出常用的使用方式。
  • Swift提供了continue,return,break跳出当前控制流程。与Java一致。
  • 判断流程。与Java类似,采用if else关键字。不同的是不需要使用()将条件包括起来。
    //语法格式 if 条件 { }else{ } //例子 var year = 1; if year == 1 { print("我一岁");//打印此语句. } else{ }
  • 选择流程。选择流程也与Java类似,采用switch cas关键字。不同的是Swift的switch不需要break;语句跳出当前匹配代码段。如果需要延续下面匹配值的代码段,则需要使用fallthrough语句,只会延续一个匹配值。
    //语法格式。 switch 值 { case 值1: 执行代码段; case 值..: 执行代码段; default: 未匹配到则执行这里。 } //例子: var year =1; switch year{ case 1: print("我1岁"); case 2: print("我两岁"); } //结果是打印 我1岁;
  • 循环流程。Swift同样提供了for 跟while 循环语句。while语句与Java一致。这里只说for语句
    //语法格式 for 变量 in 范围{ } //其中范围采用了Swfit特有的范围操作符。 //例子 for index in 1...10{ print(index);//打印1到10.如果需要只打印1到9,那么应该使用 1...<10。 }

  • Swfit提供了简约的变量赋值语句。使用了关键字guard。
    //例子 guard let name = Int("Zhou") else{ //赋值不成功则执行这里。 }

Functions [方法]
  • Swift方法声明与调用方式。Swift的调用方式与Java有一些区别,Swfit调用方法需要指定相应的参数名称。
    //声明格式。 func 方法名 (参数名:参数类型,...) ->返回值类型{ return; } //例子。 func isNumber2(number : Int) ->Bool{ if number ==2 { return true; }else{ return false; } } //调用 let is2 = isNumber2(number: 2);//调用的时候需要指定参数名称。 print(is2);//输出true;
  • 调用方法不需要输入参数名称的方式。通过在参数名称前面添加 "_"符号就可以在调用的时候不指定参数名称。例如
    //调用时:isNumber2(2);//由于声明的时候参数添加了 "_",所以不需要参数名称。 func isNumber2(_ number :Int) ->Bool{ ...}
  • 默认参数值。可以为参数指定默认值。通过在声明的时候赋值,就可以为参数添加默认值。
    //为参数number添加了默认值 3,调用的时候可以不用传入该参数值。 func isNumber2 (number :Int = 3) ->Bool{...}
  • 可变的参数值。可以为不指定参数的数量。声明的时候添加"...".例如:
    //可变的参数声明。调用的时候可以传入不等长度的参数。例如 isNumber2(12.3,34.4); isNumber2(12.4); func isNumber2(number : Double ...)->Bool{};
  • in-out 参数方式。类似于C语言中的引用传递。由于Swift Int等基本类型是值类型,所以在方法中改变该值只在该方法范围内有效。而通过指定参数为inout类型,那么就会影响到方法外该变量的值。
  • 方法也可以是一个变量参数。Swift提供了一个特性,方法也可以是一个变量或者参数。
Closures [闭包]
  • 闭包的应用之一,参数为方法的时候的简约调用方式。
    //语法 { (参数) -> 返回值 in 代码段 } //例子 let array = ["Str1","Str2"]; array.sorted(by: {(s1:String,s2:String)->Bool in return s1>s2}); //更简约的方式 array.sorted(by :{ s1,s2 in return s1 >s2});//因为参数和返回值是确定的所以不用再描述。
Enumerations [枚举]
  • Swift提供的枚举类型跟Java类似。但是比Java要更加好用些,例如Swfit可以给枚举项直接添加对应值。
    //语法。 enum 枚举名称{ case 枚举项 case 枚举项2 } 或者 enum 枚举名称{ case 枚举项1,枚举项2,枚举项3.. } //例子 enum CompassPoint{ case north case south case east case west } //引用方式 var directionTohead = CompassPoint.north; directionTohead = .east;//因为变量指定了CompassPoint类型,所以可以用这种简约的赋值方式。
  • Swfit提供给枚举类型添加相应的值。
    //语法 enum 枚举名称 : 值类型{ case 枚举项 = 值; case .. } //例子 enum Planet : Int{ case mercury = 1, venus;//mercury 对应的值为 1; } //引用方式 let mercuryValue = Planet.mercury.rawValue;//通过关键字rawValue获取值。
  • 可以通过枚举类的值获取对应的枚举项。
    let somePlanet = Planet (rawValue : 1);//这里查找值为1的枚举项,结果为mercury。
Classes and Structures [类和结构体]
  • Swift提供了两种块结构。类和结构体。类与结构体的结构和作用是类似的,只不过在不同的应用场景下需要选择相应的结构。这两者跟Java的类是类似的,都由成员变量,成员方法构成。但是区别于Java的是类的文件名称跟里面实际声明的类的名称并不需要一致。
  • 声明方式和实例化方式
    //声明方式 1) struct 结构体名称{ //结构体声明方式 //变量 //方法 } 2) class 类名称{ //类声明方式 //变量 //方法 } //实例化 struct Circle { var width :Int; var height :Int; } let circle = Circle();//实例化类或者结构体
  • 类和结构体的区别。
    1)、类是引用类型。而结构体和枚举类是值类型。
    2)、结构体倾向用于封装一些简单的数据。
    3)、类可以继承,而结构体无法被继承。
    4)、类和结构体的存储成员变量(区别与计算变量)需要在声明或者在构造函数中被初始化,否则会报错。如果有一个存储成员变量没有初始,那么在实例化的时候需要通过这个全量结构函数传入所有值,否则会报错。类和结构体默认添加了一个全量的初始化方法。
  • 判断类指向同一个实例。通过“===”和“!==”判断两个变量是否引向同一个实例。
  • Swift的String、Array、Dictionary、Set都是结构体,所以他们都是值类型。
Properties [属性/成员变量]
  • Swfit将属性按照作用分为两类,一类是存储变量,一类是计算变量,这与Java的成员变量区别很大的一点。另外跟Java一样,Swift也有成员变量和类变量的区分,一样使用static 修饰词。
  • 存储变量与Java的成员变量是一致的。计算变量的声明方式
    struct Point{ var x = 0,0,y = 0.0; } struct Rect{ var origin = Point(); var center :Point{ //center则是Swift语法中的计算变量。重新定义了获取和赋值的操作。 get{ return Point(x :2.2,y:23.3); } //如果没有写newCenter,那么默认设置的变量名是newValue,如果没有写set方法,就说明该计算变量只可读。 set(newCenter){ origin.x = 2; origin.y = 3; } } }
  • Swift成员变量调用方式。
    struct Point{ var x = 0.0,y = 0.0; } var point = Point(); let x = point.x;//获取成员变量x的值。 point.x = 1.3;//更改成员变量x的值。
  • 成员变量观察者。成员变量支持赋值改变前后的观察通知。通过willSet 和 didSet方法可以得知成员变量被改变的前后。
    //语法 class 名称{ var 变量 :类型{ willSet(新的变量值名称){ //改变值前的回调 // } didSet{//改变值后的回调 } } }
Methods [方法]
  • 方法类型。Swift中的方法跟Java一样也分为实例方法和类方法。跟Java一样,类方法也是通过添加static修饰词。
  • 关键字 self.self代表结构体、类本身。与Java的this关键字相似。
  • 方法内改变成员变量值。在结构体或者枚举类里面不可以直接改变成员变量值,需要使用关键字 mutating修饰方法才可以修改成员变量。
Inheritance [继承]
  • Swift中的类可以被继承。跟Java一样,也支持多态。
    //语法 class 名称 : 父类名称{ // } //例子 class Father { } class Son : Father{ }
  • 重写方法。Swift一样可以重写父类的方法。通过关键字override。
  • 调用父类的方法和成员变量。通过关键字super可以调用父类的方法和成员变量。
  • 重写成员变量。不但可以重写方法,Swift也可以重写成员变量的方法和观察者。
    //例子 class 类名称{ override var current :Double{ //重写的时候需要重新声明变量。 didSet{ // } } }
  • 同样,通过final 声明可以防止重写。
Initalizers [初始化]
  • 初始化类似于Java的构造函数。与Java用类名表示构造函数不同的是,Swift通过 init表示构造函数。
  • Swift将构造函数分为了两类,一类是Designated 初始化方法 和Convenience初始化方法。其中Designated就是Java中的构造函数,Convenience就是Swift对外调用提供的简约式声明方式,convenidence修饰的构造方法必须调用Designated 方法。这样重载简约的构造方法的逻辑会清晰很多,因为一定会调用普通的构造方法。
  • Swift还提供可选式样的构造函数,类似于Option值。
Deinitialization [析构函数]
  • 类似与Java类中的finalize函数。当该类实例被回收的时候就会调用该方法。方法的声明方式:
    deinit{ //处理代码 }
Automatic Reference Counting [自动引用计数器]
  • Swift也跟Java一样也有对引用的自动回收机制。
  • Swift引用计数原理。Swift的引用计数系统会跟踪属性、常量、变量对类实例的引用,如果有存在一个引用以上,则不销毁该实例。
  • 强引用循环问题。Swfit会出现强引用循环的问题,就是类实例A引用了类实例B,两者相互引用。Swift提供的解决方案是使用weak修饰符让变量成为弱引用。与Java的弱引用同出一辙。
Error Handing [异常处理]
  • Swift同样提供了异常处理的机制。跟Java的异常机制类似。
    1)、抛出异常. func throwsException () throws { throw 异常信息 } 2)、不处理异常,继续抛出异常 func throwsExceptionGoOn ()throws{ try throwsException(); } 3)、处理异常。 func handleException(){ do { try throwsException();//这里可能抛出异常 }catch(){//匹配异常 //处理异常。 }catch(){ //处理异常2 } }
  • Java有finally{}模块可以确保一些结束操作可以被执行,而Swift也提供了类似的机制,通过defer关键字可以确保里面的代码段在最后被执行。需要注意的是defer句子应该在异常代码之前被声明。并且会先于catch模块前执行。
    func processFile(filename : String) trhows{ let file open(filename); defer{ //这里的代码段会在该范围内所有代码都执行完毕才执行。 close(filename);//执行关闭操作。 } }
Type Casting [类型转换]
  • Swift提供了两种类型转换相关的语法。一种是判断,一种是转换。通过 is 关键字可以判断某个变量是否是某种类型,通过 as? 和 as!转换类型。is类似与Java InstanceOf的关键字,as类似与Java中的强制转换()。

    1) 、is。判断某个变量是否是某种类型或者某种类型的子类。
    class Animal{
    }
    let animal = Animal():
    if(animal is Animal){
    //这里会执行。
    }
    2)、as? 和as! 可以将类型转换为某种类型。
    class Animal {
    }
    class People : Animal{
    
    }
    let people = People();
    let asAnimal = people as? Animal;//现在asAnimal 是 Animal类型了
  • Swift提供了两种任意类型。Any 和AnyObject。其中可以将任何类型的变量转为Any,包括方法。而AnyObject可以代表任意一个类实例。其中AnyObject类似与Java的基类Object.

Extensions[扩展]
  • 扩展是Swift提供的新特性。可以为类、结构体、枚举类、协议扩展新的功能,不同于继承,扩展没有继承层级上的关系。可以当作是附加衍生。
  • 可扩展的内容:
    1)、计算性成员变量。
    2)、实例方法与类型方法
    3)、新构造方法
    4)、下标
    5)、实现协议
  • 扩展语法。
    1)、extension SomeType : Protocol1,Protocol2{ //添加扩展内容 } 2)、实例。为Double添加类型扩展。 extension Double{ var km:Double{return self* 1000_0.0}// } let onInch = 25.6.km;//km是新扩展的计算成员变量。
Protocols[协议]
  • 协议与Java中接口的概念是一致的。Swift协议中定义了包括方法、成员变量、类型变量的蓝图。与Java接口不同的是,协议不但可以定义方法,还可以定义成员变量。
  • 协议声明与实现:
    //协议语法 protocol Nametocol : class{.//如果添加了 class关键字,说明该协议只可以被类实现。 var fullName :String {get } statc func someType();//类型变量,也就是Java的静态变量 func someMethod(); mutating func toggle();//可更改内部变量值的方法 init()//初始化方法 //可选实现。通过添加@objct optional 关键字修饰, 该方法可以不实现。 @objc optional func optionalMethod(); } ` //协议实现 class MyName :NameProtocol{ //这里需要实现协议包含的所有内容,区分与Java这里的方法实现不需要添加override关键字 }
Generics [泛型]
  • Swift也提供了泛型,与Java泛型相似。
Access Control [访问控制]
  • Swift也提供了访问控制功能。有模块和文件两类访问控制。
  • 导入模块。通过import 关键字可以导入并使用该模块功能。与Java类似。
  • Swift提供了四种等级的访问控制。分别是public ,internal,fileprivate,private。
    • public.public定义的实体可以在自己的模块内被访问,另外其他模块如果导入了该模块,那么其他模块也可以访问该实体。
  • internal.internal定义的实体可以在自己的模块内被访问。
  • fileprivate。fileprivate定义的实体只能在该文件内被访问。
  • private.private定义的实体只能在该实体里面被访问。
  • Swift访问控制规则:一个被定义为低访问控制的实体,不能声明为高访问控制等级的任何实例。实体包括变量方法等。。
    • 例如定义了一个internal等级的ClassA,不能被声明为 public let classA :ClassA.
    • 一个方法的参数和返回值类型定义的访问权限,一定要大于或者等于该方法被声明时候的权限控制等级。
    • 跟Java一样,继承后重写的方法不能比父类的方法控制权限大。
  • Swift默认为每个实体添加了访问控制:internal.