一:可空类型
首先swift语言引进了可空类型的概念,这和objective-c是不一样的。在oc中,任何数据类型都可以是nil,但是在swift中,任何一种数据类型都有一个相对应的可空类型,下面就先展示简单的可空类型的申明和拆包装包的过程。
//定义申明
var str:String?//可空类型,在原来的类型上添加一个?
str = "asd"
print("123", separator: "123", terminator: "789")
str!.uppercaseString//可空类型不能调用(原来的方法,必须拆包),可空类型和原来的非可空类型完全是2个类型,不能直接调用原来类型的api,必须拆包(即将可空类型转换成非可空类型)
//装包和拆包
var a : Int?//定义可空类型
a = 1
func printInt(a:Int){//参数是非可空类型
print("\(a)");
}
//拆包
printInt(a!)//强制拆包,将可空类型转换成非可空类型,精度会有丢失
func printOptionalInt(a:Int?){// 参数是可空类型
print("\(a)")
}
printOptionalInt(a)//a是可空类型,不需要拆包,可以直接传递。可空的打印的是Optional(自己)
if a==nil{//只有可空类型才能跟nil做比较
print("nil")
}else{
print("real")
}
//装包(将非可空类型转换成可空类型)
var b:Int = 2
func printOther(a:Int?){
print("\(a)")
}
printOther(b)//隐式装包。装包是自动执行的,精度不会丢失。
虽然数组在swift语言中可以元素可以不固定(一个数组中可以放几种数据类型),例如:数组可以写成:
let arrayA :Array = [1,"2","3"];//数组中放了整型和字符串2中数据结构,
虽然可以,但是不建议这样,因为这样程序的可读性和维护性太差了
建议写法:
var arrayB:Array = [1,7]//初始化必须要有值
var dic:Dictionary?//必须指定键值对的类型
dic = ["1":"mike","2":"50"]//无论指定的键值对是什么类型,就算value指定的是非可空类型(如上:是String),但是取这个值的时候,仍然是可空类型
dic!["1"]取出的值仍然是可空的optional("mike"),而不是非可空的“mike”
字典的遍历可以用元组进行遍历,如下
for(key,value) in dic!{//要拆包
print("\(key,value)")
}
在swift中,枚举的定义和使用跟oc并没有什么区别,下面就是swift中枚举的定义和应用的实例:
enum Week:Int{//指定枚举中的值是整型
case Monday = 1
case Tuesday
case wednesday
case Thursday
case Friday
case Saturday
case Sunday
}
print(Week.Tuesday.rawValue)//根据枚举中的名称获取枚举值,打印值是2
enum Week2:String{//指定枚举中的值是字符串
case Monday="xingqiyi"
case Tuesday="xiangqier"
}
let i = "xingqiyi"
if let day = Week2.init(rawValue: "xingqiyi"){//根据枚举值获取枚举中的名称
switch day{
case .Monday,.Tuesday:
print("\(day)")//打印的是Monday(根据枚举值获取枚举中的名称)
}
}
enum Week3{//并不指定枚举的值
case Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
}
var weekday = Week3.Friday
switch weekday{
case Week3.Friday:
print("weekday")
case Week3.Saturday:
print("weekend")
default:
break
}
//枚举联合
enum Color{
case RGB(Int,Int,Int)
case RGBA(Int,Int,Int,Float)
case CMYK(Int,Int,Int,Int)
}
var color1 = Color.RGB(102, 102, 0);
var color2 = Color.RGBA(100, 100, 10, 0.5);
print(color1)
color1 = color2;
print(color1)
结构体和类的命名是一样的,只是一个是class,一个是struct。下面看结构体的一般用法,详情见注释:
4.1 结构体
//结构体,定义一个点的结构体
struct Point{
//x,y是存储属性,即有初始值的属性
var x = 0,y = 0
//isOrigin是计算属性(所谓计算属性,就是他没有初始值,它的初始值是从其他的属性计算得来的)
var isOrigin:Bool{
get{
return x==0 && 0 == y
}
set(origin){
if origin{
x = 0;y = 0
}
}
}
init(x _x:Int,y _y:Int){
x = _x;
y = _y;
}
//结构体的方法中不能改变自己的属性值,必须添加mutating
/*
*结构体和枚举都是属于值类型,值类型不能在它自己的实例方法中改变它自己的属性值,必须在实例方法前添加mutating,初始化方法里面不需要mutating
*类不属于值类型,因此不需要添加mutating */ mutating func addOffset(x dx:Int,y dy:Int){ x += dx y += dy } //结构体的类方法,类中的类方法只需将static关键字改成class即可 static func detaPoint(p1:Point,p2:Point) ->Point{ return Point.init(x:(p2.x-p1.x),y:(p2.y-p1.y)) } }
4.2 下标方法
oc中是没有下标方法的,下标方法是swift语言中特有的一种方法,在每个结构体和类中默认都会有一个subscript方法,即下标方法。你只需要实现这个方法,就可以快速的获取到实例中的某一个属性或者对象。如下是在结构体中用的下标方法。
struct Week4 {
var day:Array>
init(){
day = [
["englishname":"Sunday","chinesename":"星期天"],
["englishname":"Monday","chinesename":"星期一"]
];
}
subscript(index:Int)->String?{//下标方法,能够快速的获取某一天的英文名
let dic = day[index]
return dic["englishname"];
}
}
let week4 = Week4.init()
week4[0];//可以直接调用下标方法,并将下表方法的的参数设为0
class Box {
var width:Float = 0.0,height:Float = 0.0//存储变量,默认初始值都是0
init(width _width:Float,height _height:Float){//构造器
width = _width
height = _height
}
func draw(){//方法,打印宽高
print("I am a box with width\(width) and height \(height)")
}
}
let box = Box.init(width: 1.0, height: 3.0)
box.draw()
class squareBox: Box {
init(width:Float){//构造器
super.init(width: width, height: width)
}
override func draw() {//重写父类的方法。需要添加override,另外属性也是可以重写的。但是感觉在在swift中重写属性没有什么必要,因为set和get方法都必须取super值。
print("i am a squareBox with width \(self.width)")
}
}
let squareBox1 = squareBox(width: 2.0)
squareBox1.draw()
print(squareBox1.width,squareBox1.height)