Swift4.0特性

变量声明

  • 编译器自动推荐类型
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)

运算符 === 与 ==

  1. === 表示两者是否引用同一对象
var classOne = EOClass()
var classTwo = EOClass()
if classOne === ClassTwo {
   print("引用同一对象")
}
  1. == 值类型的判断
var str1= “111”
var str2= “111”
if str 1== str2 {
   print("两个值相等")
}
  1. 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 
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容

  • 简有一个银镯子,戴了好些年了。我问她什么时间买的,她记不得了。只说过它有26克,纯银的,再无其他。 好多年她都戴在...
    维夏是我阅读 95评论 0 2