Swift2
Senior进阶
Swift(二)
一、可选类型(?)
在swift中,可选类型(?)其根源是一个枚举型,里面有None和Some两种类型。其实所谓的nil就是Optional.None,非nil就是Optional.Some。
//定义一个Int类型的可选类型变量
var intNumber:Int? = 8
//把这个类型类型的变量赋值给另一个可选类型的变量
var intNumberOne:Int? = intNumber
print(intNumberOne)
//打印出来以后是一个Optional类型的值,如果要取到8,必须对可选类型强制解包
var intNumberTwo:Int? = intNumber!
print(intNumberTwo)
//可选绑定
//可选类型分为幼稚和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃。所以解包是飞航危险的
varNumber:Int?
//!表示强制解包
//var NumberOne = Number!
//print(intNumberOne)
//如果不确定可选类型是否有值时,用可选绑定,不需要对可选类型强制解包
if var intNumberTwo = Number {
print(intNumberTwo)
}
//隐式解析可选类型(!)
隐式解析可选类型和可选类型一样,都是有值和没值(nil)两种结果,区别是赋值时,隐式解析可选类型不需要强制解包。
//!隐式解析可选类型:有值,没值(nil)
var intNum:Int! = 10
//如果隐式解析可选类型的变量没值,程序一样会崩溃
//var intNumberOne = intNum
//print(intNumOne)
//可选绑定
if var intNumTwo = intNum {
print(intNumTwo)
}
一、结构体
swift的结构体对比OC来说,可以添加初始化方法、可以遵守代理协议
struct point{ struct size {
var x = 0 var width = 0
var y = 0 var height = 0
} }
声明一个结构体的格式:struct +结构体的名字 + {
声明成员变量等
}
结构体的成员方法和类方法
struct Rect {
var point:(a:int,b:int) = (0,0)
var size:(w:int,h:int) = (0,0)
//成员方法
func getSize(){
print(size)
}
//结构体的类方法:成员方法前用static修饰
static func sayHello() {
print(“heiilo”)
}
}//结构体的构造方法
var rect2:Rect = Rect(point:(10,10),size:(50,50))
//结构体有自带的构造方法
var rect:Rect = Rect(point:(10,10),size(50,50))
//调用Rect结构体的成员方法
rect.getSize()
//结构体的类方法用类名调用
Rect.sayHello()
二、类
类是人们构建代码所用的一种统一且灵活的构造体。我们可以使用与结构体完全相同的语法规则来为类定义属性(常量、变量)和添加方法。
我们通过关键字class来定义类,并在一堆大括号中定义他们的具体内容:
class ClassName {
类的内部细节
}
值类型
该类型的每个实例持有数据的副本,并且该副本对于每一个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型
//值类型
//值类型实例
stuck StructObject {
var data:int = -1
//创建一个StructObject结构体变量
var sol = StructObject()
//将sol变量的值给s02,其实是一个拷贝的过程
var s02 = so1
//so1的数据改变了,但是so2
的并没有改变
so1.data = 42
print(“\(so1.data),\(so2.data)”)//prints”42,-1”
}
引用类型
该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每一个实例都指向内存中的痛一个地址),比如类(class)就是引用类型
//引用类型事例
class ClassObject {
var data:Int = -1
//创建一个ClassObject结构体变量
var co1 = ClassObject()
//将co1变量的值赋值给co2,其实是一个引用的过程
var co2 = co1
//co1的数据改变了,但是co2也发生了改变
co1.data = 42
print(“\(co1.data),\(co2.data)”)//prints”42,42”
}
值类型与引用类型使用情形
使用值类型的情形:
使用==运算符比较实例数据的时候。
你想单独赋值一份实例数据的时候。
当在读线程环境下操作数据的时候。
使用引用类型(比如class)的情形:
当使用==运算符判断两个对象是否引用同一个对象实例的时候
当上下文需要创建一个共享的、可变的对象时。
类的定义和构造方法
定义一个Person
class Person {
var Person {
var name:String?
var age:Int?
//类的构造方法
init(name:Srting,age:Int){
self.name = name
self.age = age
}
}
计算属性与存储属性
存储属性就是类或结构体里定义的变量(或常量)。存储属性可以是变量存储属性(用关键字 var定义),也可以是常量存储属性(用关键字let定义)
除存储属性外、结构体和枚举可以定义计算属性。计算属性不直接存储值,而是提供一个getter好一个可选的setter,来简介获取和设置其他属性或变量的值。
1.定义一个Person类
class Person {
//声明存储属性
var name :String?
//声明计算属性
var number:int {
get{return 10}
set { print(newValue){
}
//初始化构造方法
init(name:String,age:int) {
self.name = name}
}
创建实例对象
var Lize = Person(name:”xiaoze”,age:20)
访问对象的name属性
print(Lize.name)
类属性和类方法
定义一个Student类
class Student {
//声明类属性
static var introduce:String?
//声明类方法(使用static和class都可以修饰类方法,区别在于:class修饰的类方法可以被子类重写)
static fun sayHi(){print(introduce)}
class func saySaWaDika(){print(introduce)}
}
//声明一个协议
@objc修饰的协议,其中额方法可以声明称可选实现(使用optional修饰)
声明一个带有可选函数的协议
@objc protocol SayHelloDelegate {
optional fun satHello ()
}
声明一个所有函数都必须实现的协议
protocol DescriptionDelegate {
func description()->String
static fun aClassMethod()->String//表示声明了一个类方法
}
//类遵守协议,直接写在本类名后面的冒号的后面,使用“,”号分隔
class ErShiXiong:NSObject,SayHelloDelegate,
DescriptionDelegate {
//必须实现的协议方法,就必须实现,否则会报错
func text(){
}
//可选协议方法,会报警告,可以添加@objc,或者继承NSObject
@objc fund test(){
}
}
四、扩展(Extension)
extension + 类型 (结构体名字)可以对一个类和结构体扩展方法
extension可以对一个类进行扩展,也可以给一个类扩展协议方法
扩展类的方法
1.//使用Extension给类扩充一个方法
extension ErShiXiong
func eat(){
print(“吃饭”)
}
}
let er = ErShiXiong()
er.eat()
//extension除了可以给类扩展方法以后,还可以给类扩展实现协议
.//先声明一个协议MyProtocol
@objc protocol MyProtocol {
optional func test () //该法方法可选实现
func test()
}
extension ErShiXiong:MyProtocol {
func test() {
print(“Hello”)
}
}
五、闭包
闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift中的闭包与C和Objective- C的代码块(block)以及其他一些编程语言中的匿名函数比较相似。
闭包可以捕获和存储其所在上下文中任意常量和变量的引用。这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift会为您管理在捕获过程中涉及到的素有内存操作
闭包表达式语句
if。语法形式
{
(参数) - >返回值类型 in
执行语句
、}
let backString = {
(name:String)->String in
return name
}
注意:闭包的函数体部分由关键字in引入,该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始
闭包的使用
使用闭包实现就两个int型数的最大值
var maxValue:((int,int)->int)
maxValue = { (a:int,b:int)->int in
return a > b ? a:b
}
print(maxValue(3,5))
其中:
1、maxValue的类型是(int,int)-> int
2、maxValue的值就是一个闭包:
{ (a:int,b:int)->int in
return a > b ? a: b}
3、其中上面的闭包还可以写成:
{a,b in a > b ?a:b}或者maxValue = {$0>$1?$0:$1}
闭包传值
创建一个工程,勾选swift语言,创建两个控制器
给第一个控制器添加导航控制器,点击按钮push到第二个控制爱,在第二个页面添加个按钮,点击返回第一个页面
class SecondViewController:UIViewController {
//声明参数为String,无返回值的闭包变量
var block = {
(struct:String)->Void in
}
闭包传值
在第二个控制器的viewDidLoad()方法创建一个返回按钮
super.viewDidLoad ()
let button:UIButton = UIButton (fram: CGeRctMake(10,100,50,50))
button.addTarget(self,action:Selector(“buttonAction”),forControlEvents:UIControlEvents.TouchUpinside)
button.setTitle(“返回”,forState:UIControlState.Normal)
button.backgroundolor = UIColor.redColor()
self.View.addSubview(button)
}
返回按钮的方法实现
fun buttonAction(){
//闭包调用
self。block!(“block返回值”)
self.navigationController?.popViewControllerAnimated(true)
}
在一地个控制器的viewDidload()方法里创建一个push按钮
override func viewDidLoad(){
superviewDidLoad()
let button:UIButton = UIButton(frame:CGRectMake(10,100,50,50))
button.addTarget(self.action:Selector(“pushAction”),forControState.Normal)
button.backgroundColor = UIColor()
self.view.addSubview(button)
}
第一个控制器的push按钮方法实现
func pushAtion () {
let secondVC:SecondViewController = SecondViewController()
secVC.View.backgroundCoor = UIColor.orangeColor()
//闭包实现,拿到传回的值
secondVC.block = {
(str:String) - >Void in
print(str)
}
self.navigationController?.pushViewController(SecondVC,animated:true)
}
//MARK: - ?和!的区别 //?代表可选类型,其实值是枚举类型,里边有None和Some两种类型,其实nil值相当于OPtional.None,如果有值相当于Optional.some //?有值,没值(nil) //! 强制解包 var number : Int? = 8 //如果没值(nil)的变量进行强制解包的情况下回造成崩溃 var number1 = number! print(number1) //可选绑定,不用强制解包 if var number2 = number { print(number2) } //!隐式解析可选类型:有值,没值(nil) //如果!强制解析没值的变量,也会造成崩溃 var intNumber : Int! = 10 var intNumber1 = intNumber print(intNumber1) //可选绑定 if var intNumber2 = intNumber { print(intNumber2) } //MARK - 结构体 //1.声明一个结构体 struct Rect { //声明结构体变量的属性(存储属性) var x:Float var y:Float var width:Float var height:Float //声明结构体属性,要使用static static var description:String? //声明一个计算属性 (是用来专门计算结构体变量属性的setter方法,和getter方法,其本身没有存储功能) var centerX:Float { //set { set { x = newValue } //get 方法 (必须得有) get { return x/2 } } var centerY:Float { return y/2 } //声明方法 //声明一个结构体变量方法 (相当于OC中的实例方法) func frameInfor(){ print("x:\(x),y:\(y),width:\(width),height:\(height)") } //声明一个结构体方法(相当于OC中的类方法),使用static修饰 static func info() { print("这是结构体方法") } } //1.根据结构体去定义一个结构体变量 var fram = Rect (x: 10, y: 10, width: 100, height: 100) //2.访问结构体变量中的属性 //注意:结构体变量中的属性类型可以使用let去修饰,只不过访问的时候不能对其进行修改 fram.x = 20 print(fram.x) //3.访问结构体属性 Rect.description = "我就是结构体属性" print(Rect.description) //4.访问计算属性 fram.centerX = 200 ; //这句话就相当于调用centerX的setter方法 let value = fram.centerX //这句话就相当于在调用centerX的getter方法 print(value) //5.调用结构体变量方法 fram.frameInfor() //6.调用结构体方法 Rect.info() //MARK: - 类(class) class Person { var name:String? var age:Int? //构造初始化方法 init(name:String,age:Int) { self.name = name; self.age = age; } //自定义初始化方式 init (name:String) { self.name = name; } //声明类属性 static var introduce:String? //计算属性 var value:Int { set(a) { age = a //在写计算 的时候,一定不能出现self,否则会早晨死循环 } get { return age! } } //声明一个类方法 //1.在类方法前边加上 static修饰 [虽然是一个类方法,但是该方法在子类中不能进行重写] static func sayHi (){ print(introduce) //注意:在类方法中只能使用类方法,不能使用对象属性 } //2.在类方法前面加上class修饰 [它是一个类方法,可以被子类重写] class func sayHi1() { print(introduce) } //声明一个实例(对象)方法 func sayHi2() { print("hello,我是实例方法") } } //1.创建对象 [此时应该注意和OC区别分开,实例对象,后边根的是类](注意:要初始化对象一定要写初始化构造的方法) var person1:Person = Person(name: "MBBoy", age: 20) //2.访问类中的属性(对象属性) print(person1.name!) //3.访问类属性 Person.introduce = "我是XXXX" //4.访问计算属性 person1.value = 20 print(person1.value) //5.访问类方法 Person.sayHi() Person.sayHi1() //6.访问实例方法 person1.sayHi2() //定义一个子类,继承Person,继承Person //在swift中不支持多继承 class Student:Person { //重写父类的方法 //重写父类中的类方法 override class func sayHi1() { print("我是子类Student类,重写了父类的类方法") } //重写父类中的实例对象 override func sayHi2() { print("我是子类Student类,重写父类中的实例对象") } // var student = Student(name: <#T##String#>, age: <#T##Int#>)) } //初始化Student对象 var student = Student(name: "张三", age: 25) Student.sayHi1() student.sayHi2() //MARK: - 值类型和引用值类型的区别 //值类型 /* struct animal { var name:String? var age:Int? init(name:String,age:Int) { self.name = name self.age = age } } var dog = animal(name: "贝贝", age: 3) var dog1 = dog //此时将dog的数据拷贝给dog1 dog.name = "欢欢" print("dog.name:\(dog.name!)") print("dog1.name:\(dog1.name!)") */ /* //引用值类型 class animal { var name:String? var age:Int? init (name:String,age:Int) { self.name = name self.age = age } } var dog = animal(name: "贝贝", age: 3) var dog1 = dog dog.name = "欢欢" print("dog.name:\(dog.name!)","dog1.name:\(dog1.name!)") */ //MARK: - 协议(protacol) //当swift中声明协议的时候,协议里有可选方法需要使用@objc关键字修饰 @objc protocol MarryDlegate { func cook() //做饭 func wash() //洗衣服 optional func hitDouDou () //打豆豆 } protocol DivorceDelegate { func diviceMonkey() //分割财产 } //如果一个类要遵循协议的时候,如果这个类有父类,要在:后先写父类,然后,再写遵循的协议 class Man:Person,MarryDlegate,DivorceDelegate{ @objc func cook() { print("还好去新东方学了几年的厨艺,终于可以大展身手") } @objc func wash() { print("还好买了台洗衣机") } func diviceMonkey() { print("分财产") } } //创建一个男人 let man = Man(name: "韦小宝", age: 22) man.cook() man.wash() man.diviceMonkey() print("分割财产") //MARK: - 扩展(Extension) //1.扩展协议中的相关方法 extension Man { @objc func hitDouDou() { print("老婆,I Miss U") } } man.hitDouDou() //2.扩展还可以扩展类方法(给某一个类添加方法,类似于OC中的category类目)以及对象方法 extension Man { //扩展一个对象方法 func sing (){ print("老婆,老婆,我爱你") } //扩展一个类方法 class func sleep() { print("多喝水,早睡觉") } } man.sing() Man.sleep() //MARK" - 闭包 //求两个数的最大值 /* 在OC中使用Block实现 int(^myBlock)(int num1, int num2) = ^int()(int num1 , int num2) { return num1 > num2 ? num1 : num2; } */ //使用闭包 var myBlock : ((num1:Int,num2:Int)->Int) //第一种使用方式 myBlock = { (num1:Int,num2:Int)->Int in //切记不能忘记in return num1 > num2 ? num1 : num2 } //第二种方式 myBlock = { num1,num2 in return num1 > num2 ? num1 : num2 } //第三那种方式 myBlock = { num1 , num2 in num1 > num2 ? num1 : num2 } //第四种方式 myBlock = { $0 > $1 ? $0 : $1 } //第五种方式 myBlock = { (num1, num2)->Int in return num1 > num2 ? num1 : num2 } let max = myBlock(num1: 88, num2: 66) print(max)