1.可选类型和强制解包(?和!)

 1> 可选类型(?)和强制解包(!)

  在swift中,可选类型(?) 其根源是一个 枚举型,里面有 None 和 Some 两种类型。其实所谓的 nil 就是 Optional.None , 非 nil 就是 Optional.Some.

  可选类型是的数据如果不进行解包的话,它是一个 Optional 类型的数据,如果我们想要使用原来类型的数据,必须进行解包

// 定义一个Int类型的可选类型变量
var intNumber:Int? =
// 把这个类型类型的变量赋值给另一个可选类型的变量
var intNumberOne:Int? = intNumber
print(intNumberOne)
// 打印出来以后是一个Optional类型的值,如果要取到8,必须对可选类型强制解包!
var intNumberTwo:Int = intNumber!
print(intNumberTwo)

  打印结果:

 2> 可选绑定

  可选类型分为有值和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃 ,所以,强制解包是非常危险的
   示例代码

// 定义一个Int类型的可选类型变量
var intNumber:Int? // 把这个类型类型的变量赋值给另一个可选类型的变量
var intNumberOne:Int? = intNumber
print(intNumberOne) var intNumberTwo:Int = intNumber!
print(intNumberTwo)

   崩溃信息:

  如果不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包

var Number:Int?
// ! 表示强制解包
//var NumberOne = Number! // 崩溃
//print(intNumberOne)
// 如果不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包
if var intNumberTwo = Number {
print(intNumberTwo)
}

 3> 隐式解析可选类型(!)

  隐式解析可选类型和可选类型一样,都是 有值 和 没值(nil) 两种结果,区别是赋值时,隐式解析可选类型不需要强制解包。

// ! 隐式解析可选类型 : 有值,没值(nil)
var intNum: Int! =
// 如果隐式解析可选类型的变量没值,程序一样会崩溃
//var intNumOne = intNum
//print(intNumOne) // 可选绑定
if var intNumTwo= intNum {
print(intNumTwo)
}

2.结构体

 1> 概述

  Swift的结构体对比OC来说,可以添加初始化方法、可以遵守代理协议等
  声明一个结构体的格式:

   struct + 结构体的名字 + {

      声明成员变量等
   }

 2> 声明一个结构体代码

 // 1. 声明一个结构体
struct Rect {
// 1.1 声明结构体变量的属性(存储属性)
var x:Float
var y:Float
var width:Float
var height:Float // 1.2 声明结构体属性,要使用static
static var desciption:String? // 1.3 声明计算属性(是用来专门计算结构体变量属性的setter和getter方法,其本身并没有存储功能)
var centerX:Float {
// setter方法
set {
// x = newValue
x = x /
} // getter方法,必须要写的方法
get {
return x /
}
} var centerY:Float {
get {
return y /
}
} // 1.4 声明方法
// 声明一个结构体变量方法(相当于OC中的实例方法) func frameInfor() {
print("x:\(x),y:\(y),width:\(width),height:\(height)")
} // 声明一个结构体方法(相当于OC中的类方法),使用static修饰
static func infor() {
print("这是结构体方法")
} } // 1. 根据结构体去定义一个结构体变量
var frame = Rect(x: , y: , width: , height: ) // 2. 访问结构体变量中的属性
// 注意:结构体变量的属性类型可以使用let去修饰,只不过访问的时候不能对其进行修改
print(frame.x) // 3. 访问结构体属性
Rect.desciption = "我是结构体属性"
print(Rect.desciption) // 4. 访问计算属性
frame.centerX = // 这句话就相当于在调用centerX的setter方法 let value = frame.centerX // 这句话就相当于在调用centerX的getter方法 print(value)
print(frame.centerY) // 5. 调用结构体变量方法
frame.frameInfor()
// 6. 调用结构体方法
Rect.infor()

 3> 代码解析

  • 声明一个结构体

  声明:代码 1 - 44行,定义一个结构体变量和对结构体的相关操作:代码46 - 68行

  结构体不需要重写初始化方法,直接可以定义一个结构体变量,代码:46 - 47

  • 声明结构体变量的属性(存储属性)

  声明:代码 3 - 7行,访问:代码49 - 50行

  结构体变量的属性可以是变量(var),也可以是常量(let),以上代码以var为例

  • 声明结构体属性

  声明:代码 9 - 10行,访问:代码53 - 55行

  要使用 static 修饰,必须由 结构体 进行访问

  • 声明计算属性

  声明:代码 12 - 30行,访问:代码57 - 63行

  用来专门计算结构体变量属性的 setter 和 getter 方法,其本身并没有存储功能,相当于OC中重写的 setter 和 getter 方法

  • 声明结构体变量方法

  声明:代码 33 - 37行,访问:代码65 - 66行

  相当于OC中的实例方法

  • 声明结构体方法

  声明:代码 39 - 42行,访问:代码67 - 68行

  使用 static 修饰,相当于OC中的类方法

  注意:类方法中只能使用 类属性,不能使用 对象属性

3.类

 1> 概述

  类是人们构建代码所用的一种通用且灵活的构造体。我们可以使用与结构体完全相同的语法规则来为类定义属性(常量、变量)和添加方法。

  我们通过关键字class来定义类,并在一对大括号中定义它们的具体内容:

   class ClassName {

    类的内部细节

   }

 2> 声明一个父类和子类的代码

 class Person {
// 1.2 对象属性
var name:String?
var age:Int? // 1.3 声明类属性
static var introduce:String? // 1.4 计算属性
var value:Int {
set {
age = newValue // 在写计算属性的时候,一定不能出现self,不然会出现死循环
} get {
return age!
}
} // 1.1 构造初始化方法
init(name:String, age:Int) {
self.name = name
self.age = age
}
// 自定义初始化方法
init(name:String) {
self.name = name
} // 1.5 声明一个类方法
// 1.5.1 在类方法前面加上一个static修饰【虽然是一个类方法,但是该方法在子类中不能进行重写】
static func sayHi() {
print(introduce) // 注意:只能使用类属性,不能使用对象属性
}
// 1.5.2 在类方法前面加上class修饰【它是一个类方法,可以被子类重写】
class func sayHello() {
print(introduce)
} // 1.6 声明一个实例(对象)方法
func sayHi1() {
print("我是实例方法")
}
} // 1. 创建对象(注意:要初始化方法)
var per : Person = Person(name: "MBBoy", age: ) // 2. 访问类中的属性
// ! 解包后为原有属性(打印结果: MBBoy ),不解包为Optional属性(打印结果 Optional(20) )
print(per.name!)
print(per.age) // 3. 访问类属性
Person.introduce = "我是xxx" // 4. 访问计算属性
per.value =
print(per.value) // 5. 访问类方法
Person.sayHello()
Person.sayHi() // 6. 访问实例方法
per.sayHi1() // 定义一个子类Student,继承Person
// Swift不支持多继承
class Student:Person {
// 重写父类的方法
// 重写父类的类方法
override class func sayHello() {
print("我是子类Student,重写父类的类方法")
} // 重写父类的实例方法
override func sayHi1() {
print("我是子类Student,重写父类的实例方法")
}
} // 初始化Student对象
var stu = Student(name: "张三", age: )

 3> 代码解析

  • 声明父类

  声明:代码 1 - 44行,初始化对象和对对象的相关操作:46 - 66行

  • 重写初始化方法

  重写:代码 20 - 28行,创建对象:代码 46 - 47行

  与结构体不同,类的初始化方法必须重写,不然不能创建对象

  • 声明对象的属性(实例属性)

  声明:代码 2 - 4行,访问:代码49 - 52行

  对象的属性可以是变量(var),也可以是常量(let),以上代码以var为例

  • 声明类属性

  声明:代码 6 - 7行,访问:代码54 - 55行

  要使用 static 修饰,必须由 类名 进行访问

  • 声明计算属性

  声明:代码 9 - 18行,访问:代码57 - 59行

  用来专门计算结构体变量属性的 setter 和 getter 方法,其本身并没有存储功能,相当于OC中重写的 setter 和 getter 方法

  在写计算属性的时候,一定不能出现 self ,不然会出现死循环

  • 计算属性与存储属性

  · 存储属性就是 类 或 结构体 里 定义的变量(或常量)。存储属性可以是变量存储属性(用关键字 var定义),也可以是常量存储属性(用关键字let定义)。

  · 除存储属性外,类、结构体和枚举可以定义计算属性。计算属性不直接存储值,而是提供一个 getter 和一个可选 的 setter,来间接获取和设置其他属性或变量的值。

  • 声明类方法

  声明:代码 30 - 38行,访问:代码61 - 63行

  注意:类方法中只能使用 类属性,不能使用 对象属性

  两种方式:

   使用 class 修饰,它是一个类方法,可以被子类重写 

   使用 static 修饰,虽然是一个类方法,但是该方法在子类中不能进行重写

  • 声明实例(对象)方法

  声明:代码 40 - 43行,访问:代码65 - 66行

  相当于OC中的实例方法

  • 声明子类

  声明:代码 68 - 81行  

  和OC相似,单继承,可以遵循协议,两者同时存在时,先在:后面写父类,后写协议,用逗号隔开

  重写父类方法,使用 override 关键字

4. 值类型和引用值类型的区别

 值类型

  • 该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型

  • 值传递只是单纯的将数据拷贝一份,赋值给一个同类型的变量,两个变量互不影响,一个值发生改变,另一个不会发生任何变化

 引用值类型

  • 该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是引用类型。

  • 值传递是将一个变量的地址赋值给另一个变量,当一个值发生改变,两个值同时改变
struct animal { // 值类型
var name:String?
var age:Int? init(name:String, age:Int) {
self.name = name
self.age = age
}
} var dog = animal(name: "贝贝", age: )
var dog1 = dog // 此时将dog的数据拷给dog1
dog.name = "欢欢" print("dog.name:\(dog.name!), 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: )
var dog1 = dog // 此时将dog的数据拷给dog1
dog.name = "欢欢" print("dog.name:\(dog.name!), dog1.name:\(dog1.name!)")

  打印结果:

 值类型与引用类型使用情形

  • 使用值类型的情形:

  使用 == 运算符比较实例数据的时候。

  你想单独复制一份实例数据的时候。

  当在多线程环境下操作数据的时候。

  • 使用引用类型(比如class)的情形:

  当使用 === 运算符判断两个对象是否引用同一个对象实例的时候。

  当上下文需要创建一个共享的、可变的对象时。

5.协议

 1> 概述

  • 协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性

  • 类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能

  • 任意能够满足协议要求的类型被称为遵循(conform)这个协议

 2> 声明协议

  • @objc 修饰的协议,其中的方法可以声明成可选实现(使用optional修饰)
@objc protocol SayHelloDelegate {
optional func sayHello()
}
  • 声明一个所有函数都必须实现的协议。
protocol DescriptionDelegate {
func description() -> String
static func aClassMethod() ->String//表示声明了一个类方法
}

 3> 遵守协议

  类遵守协议,直接写在本类名后面的冒号的后面,使用 "," 号分隔

class ErShiXiong: NSObject,SayHelloDelegate, DescripationDelegate {
// 必须实现的协议方法,就必须实现,否则会报错
func test() {
}
// 可选协议方法,会报警告,可以添加 @objc, 或者继承NSObject
@objc func test1() {
}
}

6.扩展(Extension)

 1> 概述

  extension + 类名(结构体名字)可以对一个类和结构体扩展方法,类似于 OC 的 Category 类目

  extension 可以多次对一个类进行扩展,也可以给一个类扩展协议方法

 2> 使用Extension给类扩充一个方法

extension ErShiXiong {
func eat() {
print("吃饭")
}
}
let er = ErShiXiong()
er.eat()

 3> 给类扩展实现协议

//先声明一个协议MyProtocol
@objc protocol MyProtocol {
optional func test() //该法方法可选实现
func test()
} extension ErShiXiong: MyProtocol {
func test() {
print("Hello")
}
}

7.闭包

 1> 概述  

  • 闭包是自包含的函数代码块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C 中的 代码块(block)以及其他一些编程语言中的 匿名函数 比较相似。

  • 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。。

 2> 语法形式

  {

   (参数)-> 返回值类型  in
       执行语句
  }

 3> 闭包的使用(五种方式)

// 声明
var myBlock : ((num1:Int, num2:Int) ->Int) // 第一种使用方式
myBlock = {
(num1:Int,num2:Int)->Int in // 切记不能忘记 in return num1 > num2 ? num1 : num2
} // 第二种使用方式
myBlock = {
(num1,num2)->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 = {
$ > $ ? $ : $
} let max = myBlock(num1: , num2: )
print(max)

 4> 闭包传值(和OC中的Block传值类型)

  需求:创建一个工程,勾选swift语言,创建两个控制器给第一个控制器添加导航控制器,点击按钮push到第二个控制器,在第二个页面添加个按钮,点击返回第一个页面,并将第二页textField中输入的值传到第一页,并在第一页的textField中显示

  在第二页声明参数为String,无返回值的闭包变量,用于传值

class SecondViewController: UIViewController {
// 声明参数为String,无返回值的闭包变量
var block = {
(str: String) -> Void in
} ... }

  在第二页的返回按钮的方法调用闭包

fun buttonAction (){
// 闭包调用
self.block!("block返回值")
self.navigationController?.popViewControllerAnimated(true)
}

  在第一页的push按钮中实现闭包

fun pushAction (){
let secondVC: SecondViewController = SecondViewController()
secondVC.view.backgroundColor = UIColor.orangeColor()
// 闭包实现,拿到传回的值
secondVC.block = {
(str: String) -> Void in
self.textField?.text = str
}
self.navigationController?.pushViewController(secondVC, animated: true)

  注意:在class类中声明变量 最好立刻初始化 或 定义为可选变量,不然该类必须重写初始化方法

【原】iOS学习之Swift之语法2(精简版)的更多相关文章

  1. 【原】iOS学习之Swift之语法1(精简版)

    1. Swift简介 2010年的夏天,苹果公司的开发人员Chris Lattne接到了一个特别的任务,为OS X 和iOS平台开发下一代的编程语言,也就是Swift. 苹果公司于2014年WWDC( ...

  2. Swift之语法1(精简版)

    1. Swift简介 2010年的夏天,苹果公司的开发人员Chris Lattne接到了一个特别的任务,为OS X 和iOS平台开发下一代的编程语言,也就是Swift. 苹果公司于2014年WWDC( ...

  3. iOS: 学习笔记, Swift与C指针交互(译)

    Swift与C指针交互 Objective-C和C API经常需要使用指针. 在设计上, Swift数据类型可以自然的与基于指针的Cocoa API一起工作, Swift自动处理几种常用的指针参数. ...

  4. iOS: 学习笔记, Swift与Objective-C混用简明教程(转载)

    Swift与Objective-C混用简明教程 转载自:https://github.com/lifedim/SwiftCasts/tree/master/000_mix_swift_objc 我想很 ...

  5. IOS学习[Swift中跳转与传值]

    Swift中页面跳转与传值: 1.简单方式 首先,Swift的跳转可分为利用xib文件跳转与storyboard跳转两种方法,我这里选择使用storyboard的界面跳转方法. 1.通过在storyb ...

  6. IOS学习笔记39--NSString各种语法的使用

    今天就NSString的各种语法学习学习,以后慢慢补充: 1.字符串的遍历 NSString *string = @"CHENGWULI"; //字符串的长度 int count ...

  7. iOS: 学习笔记, Swift名字空间

    在Swift中, 名字空间是用class(extension)嵌套来实现的, 下面用一个简单例子来进行展示 // // main.swift // SwiftNameSpace // // Creat ...

  8. iOS: 学习笔记, Swift运算符定义

    Swift操作符可以自行定义, 只需要加上简单的标志符即可. @infix 中置运算. 如+,-,*,/运算 @prefix 前置运算. 如- @postfix 后置运算. a++, a-- @ass ...

  9. iOS: 学习笔记, Swift与Objective-C混用总结

    Swift与Objective-C交互总结 在Swift中使用Objective-C(简单) 在创建OjbC文件时, XCode会提示创建XXX-Bridging-Header.h文件, 创建之 在创 ...

随机推荐

  1. oracle dataguard (一)

    一.什么是data guard及data guard的工作原理 Data Guard 是一个集合,由一个primary数据库(生产数据库)及一个或多个standby数据库(最多9个)组成.组成Data ...

  2. 【转载】 Pyqt 利用QDataStream对文件进行存取

    # -*- coding: utf-8 -*- from PyQt4.QtGui import * from PyQt4.QtCore import * import sys QTextCodec.s ...

  3. 无废话ExtJs 入门教程五[文本框:TextField]

    无废话ExtJs 入门教程五[文本框:TextField] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在表单里加了个两个文本框.如下所示代码区的第42行位置,items: ...

  4. python检测文件的MD5值

    python检测文件的MD5值MD5(单向散列算法)的全称是Message-Digest Algorithm 5(信息-摘要算法),经MD2.MD3和MD4发展而来.MD5算法的使用不需要支付任何版权 ...

  5. 手机WEB自适应头部代码

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> < ...

  6. TortoiseSVN常用操作说明

    TortoiseSVN是windows下其中一个非常优秀的SVN客户端工具.通过使用它,我们可以可视化的管理我们的版本库.不过由于它只是一个客户端,所以它不能对版本库进行权限管理. TortoiseS ...

  7. 2015最新移动App设计尺寸视觉规范【图文版】(转)

    如今手机app的屏幕设计尺寸参差不齐,仿佛来到了移动界面尺寸战国时代,每家移动设备制造公司都为了迎合大众的口味,各家都在2014年大放光彩.2015年也将会是我们移动APP设计界快速发展的一年. 因为 ...

  8. App界面交互设计规范(转)

    在上篇<APP界面设计风格>确定下来后,产品经理(兼交互设计)还不用着急将所有的交互稿扔给设计师进行细致的界面设计.在细节设计启动前,拉上设计师和安卓前端开发.ios前端开发一起商议确定设 ...

  9. loj 1038(dp求期望)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25915 题意:求一个数不断地除以他的因子,直到变成1的时候 除的次 ...

  10. commonlisp教程以及学习笔记-01

    手上有两个教程,但是感觉这个教程可能更适合自己