Swift4.0特性
2019-03-14 本文已影响0人
找不到工作的iOS
变量声明
- 编译器自动推荐类型
let testOne = 20
var testTwo = 30
let stringOne = "123"
- 不使用编译器自动推荐类型
let stringOne:String = "123"
- 不同类型的加减
- 这里不是强转,是重新初始化了一个变量
- swift不会自动转化类型(隐式转换),必须自己亲自操作
let testOne = 20
var testTwo : Double = 30;
var Three = testOne + Int(testTwo)
var Four = Double(testOne) + testTwo
- 打印
print(testOne,testTwo)
print("值一:\(testOne),值2:\(testTwo)")
类型转换
- 强转 as
- ? (optional 可以有值,可以没值) 的意思就是这个testOne可能无法转换,可能会转化成空值
- 没有值时用!会崩溃,!隐式解析
let testOne = 20
let testTwo = testOne as? Double // 无法转化
var stringOne : String?
- 一般可以转化成功的情况(上面的不行,为nil)
- 错误案例
var testArray = ["1234","5678"]
testArray[1] = 456
- 正确案例
var testArray = ["1234","5678"]
var testArrayTwo = testArray as? Array<any>
testArrayTwo![1] = 456
数组
- 可变与不可变的数据
let arrayOne = ["123","456"]
var mutableArray = ["123","456"]
mutableArray.append("789")
var arrayThree = Array<String>();
var arrayFour = Array<Any>();
var arrayFive = [any]()
字典
- 声明
var dic = [
"key":"value",
"key":"value",
]
var dicTwo = [String:String]()
dicTwo["keyOne"] = "valueOne"
var dicThree = Dictionary<String:String>()
dicThree ["keyOne"] = "valueOne"
- 是否为空
if (dic.isEmpty) {
}
循环
- for in (1...5)闭区间1到5
for index in 1...5 {
}
- for in (1..<5) 不包含5
for index in 1..<5 {
}
- 无索尼,执行5次
for _ in 1...5 {
}
- 数组遍历
var names = ["1","2","3","4"]
for number in names {
}
for (index,number) in names.enumerated {
}
- 数组倒叙
for value in array.reversed() {
- 字典遍历(元祖)
var dic = ["key1":"1","key2":"2","key3":"3"]
for (key,value) in dic {
}
- 字符串遍历
for charac in "hello"{
}
- repeat while 代替 do while, 单独while还一样
repeat {
count = count + 1
} while count < 5
while count < 5 {
}
元祖
- 多个值组成的复合值,可以是任意类型
let http404 = (404,"error")
print(http404.0,http404.1)
- 给元祖赋值.
let(statusCode,statusDes) = http404
print(statusCode,statusDes)
let(statusCode,_) = http404
- 给元祖定义名字
let http200Status = (status:200,des:"success")
print(http200Status.status,http200Status.des)
条件语句 if
- 和oc的区别是必须是一个bool表达式,不会和oc那样帮你隐式转化
- 错误案例
let testStr = "123"
if testStr {
}
- 正确方式 (这个?必须要有,否则编译报错)
let testStr:<String>? = "123"
if let condtion = testStr {
print("condtion is ture")
}
if testStr != nil {
}
条件语句 switch
- 省略了break
- fallthrough继续执行
- 每一个case分支都必须写上代码
let characterTest:Character = "1"
switch characterTest {
case "1","一":
print(characterTest)
fallthrough
case "2":
print(characterTest)
case "3":
print(characterTest)
default:
print("not")
}
- 区间匹配
let num = 3000
var str:String
switch num{
case 0...9:
str = "个"
case 10...999:
str = "百"
case 1000...9999:
str = "千"
default:
print("万")
}
- 元组匹配
let point = (1,1)
switch point{
case (0,0):
print("在原点")
case (0,_):
print("x")
case (_,0):
print("y")
case (-2...2,-2...2)
print("要求范围内")
default:
print("不在轴上")
}
- 值绑定 ,输出 “在x轴的位置:3”
- 允许将匹配的值绑定到一个临时变量
let point = (3,0)
switch point{
case (let x,0):
print("在x轴的位置:\(x)")
case (0,let y):
print("在x轴的位置:\(y)")
case (let x,let y):
print("point:\(x) \(y)")
default:
print("不在轴上")
}
let point = (3,0)
switch point{
case let(x,y):
print("point:\(x) \(y)")
default:
print("不在轴上")
}
方法
- 1.无返回值函数
fun testMethod() {
print("testMethod")
}
testMethod()
- 2.有参数 有返回值
fun testMethod(number1:Int, number2:Int) -> Int {
return number1 + number2
}
testMethod(number1:2,number2:8)
- 3.多个返回值 元组的方式
fun testMethod(numberArray:Array<Int>) -> (max:Int,min:Int,sum:int) {
return (100,1,101)
}
testMethod([1,2,3])
- 4.定义外部参数名,增加可读性
fun testMethod(fristStr str1:String ,secondStr str2:String) -> String {
return str1 + str2;
}
testMethod(fristStr:"123",secondStr:"456");
- 5.忽略参数名
fun testMethod(_str1:String ,_str2:String) -> String {
return str1 + str2;
}
testMethod("123","456");
- 6.给参数设默认值(要放在参数列表最后)
fun testMethod( str1:String ,str2:String = “abc”) -> String {
return str1 + str2;
// "123abc"
}
testMethod(str1:"123");
- 7.可变参数 不确定参数的数量(要放在参数列表最后,并且只能有一个可变参)
fun testMethod( argNumbers:Int ...) -> Int {
var sum = 0
for number in argNumbers {
sum += number
}
return sum;
}
testMethod(argNumbers :1,2,3,4,5,6,7);
- 8.输入输出参数(inout):如果想要一个函数的参数和外部传过来的是同一个参数,即函数内部对外部参数修改
- 不能有默认值
fun swap( inout num1:Int, inout num2:Int.) {
var temp = num1
num1 = num2
num2 = temp
}
var numberOne = 1
var numberTwo = 9
swap(num1:&numberOne, &num2:numberTwo)
- 9.函数类型(函数可以赋值给变量,可以作为参数,可以作为返回值,函数内部可以嵌套函数)
- 赋值
func testMethod(num1:Int,num2:Int) -> Int {
return num1 + num2
}
var methodVar : (Int,Int)->Int = testMethod
methodVar(1,2)
- 作为参数
func testMethod(num1:Int,num2:Int) -> Int {
return num1 + num2
}
func testMethodTwo(parameterMethod:(Int,Int)->Int, _ parameter1:Int,_ parameter2:Int) {
let result = parameterMethod(parameter1,parameter2)
}
- 作为返回值
func testone (p:Int,p2:Int)- {
}
func testtwo (p:Int,p2:Int)- {
}
func testMethodThree(_ condition:Bool) -> (Int,Int)->Int {
return condition? testone : testtwo
}
- 函数嵌套
func testMethodThree(_ condition:Bool) -> (Int,Int)->Int {
func testone (p:Int,p2:Int)- {
}
func testtwo (p:Int,p2:Int)- {
}
return condition? testone : testtwo
}
-
defer 延迟执行 (打印结果 1 2 3)
···
func testOne ()->Int {defer {
testTwo()
}
print("1")
return 3;
}
func testTwo ()->Int {
print("2")
}
··· -
defer 场景之现场安全,配合锁比oc方便很多(不用去管解锁操作,也不会忘记解锁)
let _testLock = NSLock.init()
var _testCount = 0
// 做一个线程安全
var testCount : Int {
set {
_testLock.lock()
defer {
_testLock.unlock()
}
_testCount = newValue
}
get {
_testLock.lock()
defer {
_testLock.unlock()
}
return _testCount;
}
}
闭包
- 方法:
func方法名(参数) -> 返回值 {
函数体
} - 闭包:
{ (参数) -> 返回值 in
函数体
} - 1.1 传方法进闭包
func testMethod (num1:Int,num2:Int) -> Bool {
return num1 > num2
}
let names = [1,2,3,4,5]
let nameSortFour = names.sorted(by:testMethod)
- 1.2 针对单行函数体,可以隐藏返回值
let names = [1,2,3,4,5]
let nameSortFour = names.sorted {(num1,num2) in num1 > num 2}
print(nameSortFour) // 5 4 3 2 1
- 1.3 参数名可以缩写(swift自动提供了参数名称)
let names = [1,2,3,4,5]
// 写法1
let nameSortFour = names.sorted () {
return $0 > $1
}
// 写法2
let nameSortFour = names.sorted {$0 > $1}
- 2.1 尾随闭包
func testMethod (styleMethod:()->()) {
styleMethod()
}
// 正规写法
testMethod(styleMethod:{
print("闭包调用")
})
- 2.1.1 简写版本
func testMethod (styleMethod:()->()) {
styleMethod()
}
// 编译器会提示的省略版本(当函数只有闭包一个参数时)
testMethod {
print("闭包调用")
}
- 2.1.2 忽略参数名
func testMethod (_ styleMethod:()->()) {
styleMethod()
}
testMethod ({
print("闭包调用")
})
- 3.循环引用问题的解决
- ?? 如果weakself为空,返回后面的值
var nameMethod = ((Int) -> String)?
override func viewDidLoad () {
super.viewDidLoad()
self.title = "testName"
weak var weakSelf = self
nameMethod = { num in
return weakSelf?.title ?? ""
}
print(nameMethod!(1))
deinit {
print("delloca")
}
}
- @escape 闭包逃逸(闭包的调用不在当前的函数内,比如异步)
func testMethod( closure:@escape ()->void) {
DispatchQueue.main.async {
closure()
}
}
枚举
- swith的枚举不会有默认值,oc会有默认值0,1,2,3
func 枚举() {
enum CompassPoint {
case North
case West
case East
case South
}
print(CompassPoint.North)
var direction = CompassPoint.North
direction = .South
let directionTow : CompassPoint = .West
switch (directioTow) {
case: .North
print("北")
case: .West
print("西")
}
}
- swith手动定义枚举默认值(int float double),根据第一个赋的值自动递增
enum CompassPoint {
case North = 2
case West // 3
case East // 4
case South // 5
}
- 绑定自定义值
enum CompassPoint {
case North(String,Int)
case West (Double)
case East // 4
case South // 5
}
var directionOne = CompassPoint.North("北方",2)
var directionTwo = CompassPoint.West(3.0)
switch (directionOne ) {
case .North(let direction, let number) :
print("方向\(direction) 数字\(number)")
case .West(let doubleNum) :
print("浮点数\(doubleNum)")
}
- 通过rawValue根据参数寻找指定枚举值,(通过int不一定能找得到所以返回的是可选值)
enum CompassPoint {
case North = 1
case West
case East
case South
}
let direction = CompassPoint(rawValue;1) // North
let direction = CompassPoint(rawValue;5) // nil
}
结构体与类的区别
- 1.结构体是值类型(拷贝),类是指针类型(引用)
struct testStruct {
var name = "ken"
var age = 9
}
var structOne = testStruct()
let structTwo = structOne
structOne.age = 10
print(stuctTwo.age) // 还是9
- 2.结构体 有一个自动生成的成员逐一构造函数,用于初始化结构体实例中的成员属性(类没有这种构造函数)
struct testStruct {
var name = "ken"
var age = 9
}
var testStructTwo = testStruct(name:"sun",age:15)
运算符 === 与 ==
- === 表示两者是否引用同一对象
var classOne = EOClass()
var classTwo = EOClass()
if classOne === ClassTwo {
print("引用同一对象")
}
- == 值类型的判断
var str1= “111”
var str2= “111”
if str 1== str2 {
print("两个值相等")
}
- swift的所有基础类型是值类型(拷贝行为)Int Double String Bool Array Dictionary
属性
- 延迟加载lazy
lazy var
-
get set
swift属性.png -
只读
swift属性2.png -
外部变量名增加可读性
属性3.png -
属性观察
属性观察4.png -
类的属性使用关键字 static
属性1.png -
类方法 (结构体 static func, 类 class/static func)
类方法.png -
mutating:结构体内的属性不可在实例方法中改变,要的话用mutating修饰
修改结构体属性.png
subscript下标运算
struct TestTable{
subscript(index:Int) -> String {
return ""
}
subscript(key:String) -> String {
return ""
}
}
var testTable = TestTable()
var value = testTable[1]
var value2 = testTable["key"]
继承
- 结构没有继承
- override重写父类方法
class OneClass {
func method () {
}
}
class SubClass : OneClass {
override func method() {
}
}
- final 防止子类重写方法 (final var mfinal class func, final func, final class 类A (不能被继承的类))
class OneClass {
final func method () {
}
}
class SubClass : OneClass {
override func method() {
}
}
构造
- 简写与正常写法
var oneTest = ClassOne()
var oneTest = ClassOne.init()
- 重写了init构造后,就不用使用简写方式
class OneClass {
init (name:String) {
}
}
var testClass = OneClass() // 这样就不行了
var testClass = OneClass(name:"111")
var testClass = OneClass,init(name:"111") //正式写法
- 构造函数里可以修改常量let (子类不行)
class OneClass {
let name:String
init (name:String) {
self.name = name
}
}
class SubClass : OneClass {
override init (name:String) {
super.init(name:name)
}
}
- 结构体中如果重写构造函数,默认的结构体构造器也不能访问
- 如果子类有变量,父类init要放在子类init最后
class OneClass {
let name:String
init (name:String) {
self.name = name
}
}
class SubClass : OneClass {
var subname
override init (name:String) {
subname = ""
super.init(name:name)// 为了安全放在最后
}
}
- 便利构造器
- 可失败构造器
- 析构函数 deinit
- 拓展 extent
- 协议
protocol OneProtocol {
func method()
var name:String {get set} // 表示可读可写
static func classMethod()
mutating func changeProperty()
}
class TwoClass:OneProtocol {
func method() {
// 实现
}
name:String = "123"
static func classMethod {
}
func changeProperty {
}
}
// 有父类
class TwoClass:OneClass:OneProtocol {
}
- 委托协议
protocol OneProtocol {
}
protocol TwoProtocol {
}
class TestClass {
var delegate:OneProtocol?
var delegate2:(OneProtocol & TwoProtocol)
}
- 可选协议
@objc protocol TwoProtocol {
@objc optional func testMethod()
}
class TestClass:TwoProtocol {
func testMethod {
print("实现了可选方法")
}
}
override viewDidLoad() {
let testClass = TestClass()
(testClass as TwoProtocol) .testMethod?() // ? 如果有实现协议的方法,就执行
}
- 泛型
func swapTwoInt(_ num1:inout Int ,_ num2:inout Int) {
let temp = num1
num1 = num2
num2 = temp
}
func swapTwo<T>(_ num1:inout T,_ num2 inout T) {
let temp = num1
num1 = num2
num2 = temp
}
swapTwo(&num1,&num2)
swapTwo(&str1,&str2)
- 运算符重载 (=不能重载)
struct Vector2D {
var x = 2
var y = 3
static func + (left:Vector2D ,right:Vector2D) -> Vector2D {
return Vector2D (left.x + right.x , left.y + right.y)
}
static prefix func ++ (left: inout Vector2D ) {
left.x = left.x + 1
left.y = left.y + 1
}
static func += (left:inout Vector2D , right:Vector2D ) {
left = left + right
}
}
override func viewDidLoad() {
var Vector1 = Vector2D ()
var Vector2 = Vector2D ()
var Vector3 = Vector1 + Vector2
++Vector3
Vector3 =+ Vector1
}