Swift2

Posted J_维他命_M

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)

  

以上是关于Swift2的主要内容,如果未能解决你的问题,请参考以下文章

NSFetchRequest 上的 Swift2.0 CoreData 问题

swift2 AVAudioRecorder

(swift2) 变量在 if 语句中没有变化

从 swift 1.2 迁移后 swift2 中的 healthKit 错误

从 swift 1.2 迁移后 swift2 中的 healthKit 错误

Swift2.0 UITextView 和 UITextFile 的使用