swift学习笔记

Swift是强类型语言,所有变量都是强类型


传递参数时候,只要传递的参数不是类或者类的实例,那传递过的参数都是拷贝过的,即都是值;字典和数组在swift中是结构体。不是类,结构体和类两大区别:

1,结构体不能继承,而类可以

2,结构体传递的是值,而类传递的是引用。



常规的数组声明:Array<类型>(),例如:

  var test2 = Array<Double>()

        test2.append(10)

        test2.append(100)

        print(test2)//输出[10.0, 100.0]

或者在方括号内写入类型来声明数组,例如:

var test = [String]()

 test.append("test1")

test.append("test2")

print(test)//输出[“test1", "test2"]


常规的字典声明: Dictionary<key, value>() 例如:

var knowOps =  Dictionary<String, Int>()

或者以[keyvalue]的方式声明,例如上式等同于:

var knowOps = [String:Int]()



但函数需要多个参数并使用闭包时,只有最后一个参数可以写在括号外,其余还是括号内


swift中,允许方法名相同,但是参数必须不同



Required关键字

在函数前面加Required,则子类必须实现该函数



NSFileManager.defaultManager()返回默认实例,只能在主线程使用,若需要在其他线程使用,需要新建一个NSFileManager实例,例如:

    let manager = NSFileManager()

一个线程只有一个NSFileManager实例,当前线程的NSFileManager实例不能在其他线程使用




var 声明的为变量,let为常量,常量只能赋值一次

后面确定不再赋值的最好用let


变量和定量声明时候都需要声明类型,如果不声明类型那就需要直接赋值

例如:

var test:Int  

var test = 1

var test (报错)


变量和定量声明之后都可以不用赋值,但不能为nil,声明用『!』的变量或常量,不能被nil赋值(输出则程序奔溃,但可以编译),声明用『?』的变量或常量可被nil赋值(输出也不会奔溃)

例子:

var test: Int?

        test = nil

        print(test)//输出nil

var test: Int

        test = nil       //这一步可以正常运行但没有赋值到

        print(test)     //程序奔溃




声明类型用『!』,后面取值不用加『!』

例如:

var test:Int 

var test2:Int = test +1


若是用『?』,则后面取值要加『!』。赋值的时候不用加

例如:

var test:Int?

vat test2:Int? = test!!+1

test2 = 10


布尔值

Swift为布尔量提供了两个常量值, true false 


元组

声明格式:  var aTupe =”A”2 ——无标签,通过索引取值

例如:var test = aTupe.0   ——————test ==“A”

声明格式:let bTupe = (first”one”second:”two”) ———通过前置标签取值

例如:let test = bTupe.first ——————test ==“one”

特殊用法;

        let http404Error = (404, "Not Found")

        let (statusCode, statusMessage) = http404Error

        print("The status code is \(statusCode)")  //The status code is 404









数组

声明例子: let test :[Int] = [1,2,3,4]

        var test2 = ["a","b","c"]

        let test3 = [Int]()   //不为空,count = 0

        let test4: [Int]? // 此时为空

常规方法:

        array.insert(2, atIndex: 0)  //索引0插入2

        array.append(4)   //后面加上4

  array.removeAtIndex(4) //移除索引为4的值


字典

声明例子: var dic = ["fiest":"one", "sencond":2]

赋值:  dic["thid"] = 4     

//dic此时为["fiest": one, "sencond": 2, "thid": 4]

取值 dic.first!

//比较特别的例子:

var dic =  [“key”: “value”]

dic str1: String?

str1 = nil

dic[“key”] = str1

//此时dic[“key”]是存在的,值为nil,可以输出dic[“key”: nil]

var dic2 =  [“key”: “value”]

dic2[“key”] = nil

//此时dic2[“key”]是不存在的,即成功删除 key-value键值对

注意:

Dictionary value 类型为 String时,如果你要设置它的值,它接受的是一个 String?类型的参数





for循环

例子:for obj in 1..<10 {

            num++

        }

          for obj in 1…10 {

            num++

        }

       for var obj = 1; obj < 10; obj++ {

                 num++

        }


//…表示1~10..<表示1~9


switch

格式:switch XX {

           case  a

                  //a必须与XX同类型

                 //需要执行的内容

                //不需要break结尾

           case b

                //同上

         default

              //必须实现default

}


类别名 typealias

用于给已存在的类取其他名字

例如:

         typealias myInt = Int

        var test2:myInt!   //此时myInt相当于Int

        test2 = 5       

 //函数类型也可以作为别名

例子:  typealias intFunction = Int -> Int



断言 assert(条件)

例子: let age = -3

        assert(age > 0)

        print("next")  //此时没有输出next,因为条件不符合

//代码执行只要在 if age >= 0 评定为 true 时才会继续,就是说,如果 age 的值非负。如果 age 的值是负数,在上文的代码当中, age>= 0 评定为 false ,断言就会被触发,终止应用。



函数

基本格式:  func 函数名(参数列表) -> 返回类型 {

                    //code

                     //可以在里面继续添加函数(方法)

}

例子: func myMethod2 (var firstName fitst: Int,var second: Int) ->NSString {

        

        func myMethod2_c (one: Int, two: Int) ->Int {

            return one+two

        }

        fitst = myMethod2_c(1, two: 1)

        return "yes:\(fitst),\(second)";

    }

//(var firstName fitst: Int,var second: Int) 表示第一个参数名字为firstname,第2个参数没有设置名字则默认为second

//     myMethod2(firstName: 1, second: 1) 为调用时候的格式

//firstName就是外部名字,first就是内部名字


//当返回类型为void的时候不填写返回参数

例子:

 func getAll() {

    

    }

当函数作为变量的时候

格式: var 名字(类型)  ->返回类型

//当返回类型为空的时候,则为返回类型=()

例子: var myMethod:(Int) ->()




继承

格式 class XX :  DD {

           override init (){

            //code

          }

         convenience init(参数列表) {

                  self.init()  //这步是必须的

                  //code

            }

       deist {

           //retaincount=0的时候运行该函数

         //释放内存的工作

                }

}

例子: class  animal {

    var name: NSString?

    var sex: NSString?

    init(){

        print("create animal")

    }

 

}

class Dog: animal {

    var all:NSString? {

        return "name : \(self.name) ,sex: \(self.sex)"

    }

    override init (){

      print("dog create")

    }

    convenience init(name: NSString) {

        self.init() //必须的一步

        //其他初始化工作

    }

    //重载初始化函数

    init(name: NSString, sex: NSString){

        super.init()  //如果下面要使用父类成员,则此步是必须的

        self.name = "a"

        print("!!")

         //若前面不执行 super.init(),则在子类init执行完毕后,才会自动执行父类init(),之后就可以使用父类的成员

    }

}

//当重载的init与需要调用原来的init时候,需要在前面添加convenience

//若父类有重载init方法,则子类中的init方法必须调用父类的重载方法

//顺序:先初始化子类自己的成员,在调用父类对应的初始化方法

//特别注意:只有类的成员方法才能引用self来表示调用该成员方法的对象引用,闭包对象(成员)不能用self


变量可重写getset方法,不写就要初始值

例子:

class Rectangle {

    var wid: Double = 0

    var hei: Double = 0

    var area: Double {

        get {

            return wid * hei

        }

        set {

            wid = sqrt(newValue)

            hei = newValue

        }

    }

}


其他用法:

class Rectangle {

    var wid: Double = 0

    var hei: Double = 0

    var area: Double {

        get {

            return wid * hei

        }

        set {

            wid = sqrt(newValue)

            hei = newValue

        }

    }

    var sum: Double = 0 {

        willSet(new) {

            print("new is :\(new)")

        }

        didSet(old) {

            print("did set is :\(old)”)

        }

    }

}

// var test:Rectangle = Rectangle()

        test.sum = 10

        print(test.sum)

//输出以下语句: new is :10.0

did set is :0.0

10.0

//getsetdidSetwillSet不能共存

//希望同时使用getsetdidiSet,willSet,只需要重写属性成员即可,如下:

class ClassA {

    var num: Int {

        get {

            print("get")

            return 100

         }

        set {

            print("set")

        }

 

    }

    init() {

        num = 0

    }

}

class ClassB: ClassA {

    override var num: Int {

        didSet{

            print("didiset")

 

        }

        willSet{

            print("will set")

        }

    }

}

//输出顺序分别是:will set

set

didiset

get



惰性加载 lazy :在引用到的时候才开始创建

例子:

class animal {

    init() {

        print("animal is create")

    }

}

class Dog {

    var animal1 = animal()

    lazy var animal2 = animal ()

    init() {

        print("dog is create")

    }

}

引用:     var dog = Dog()

        print("我是分割线")

        print("i am \(dog.animal2)")

输出情况

animal is create

dog is create

我是分割线

animal is create

i am one.animal

ps:只有var才能使用lazy特性


协议 protocol

继承协议的类或结构体,必须声明好protocol所有方法和函数

例子:

class Jo: Book {

    var name: NSString = "jo"

    var age: Int = 10

    mutating func getAll( first: NSString) {

        print(first)

    }

}

protocol Book {

    var name: NSString {get}   //该属性必须可以获取

    var age: Int {set get}    //该属性必须可获取和设置

   mutating func getAll(var first: NSString) ->()   //必须存在该函数

}

//协议内声明的属性必须用{ }标注set或者get,不能为空 

//一般情况下,在protocol声明后加:@class,表示该协议只能被class遵守,structenum等不能遵守,此时才能使用weak delegate

eg: protocol  Book:class (此时协议不能使用mutating声明)

//或者使用@objc的方式,例子:

@objc protocol UIScrollViewDelegate {

    optional func scrollViewDidScroll(scrollView: UIScrollView)

    optional func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView

//若协议中存在属性成员,则子类也需要用@objc关键字声明该属性成员

//optional表示可选

    …

}


//所有属性都只能用var,不能用let

//协议方法都用mutating声明

//mutating作用:为了能在方法中修改structenum的变量.

例子:protocol MyProtocol {

    var myColor: UIColor {get set}

    mutating func change() -> ()

}

struct MyTest:MyProtocol {

    var myColor: UIColor = UIColor.redColor()

    mutating func change() {

        myColor = UIColor.yellowColor()

    }

}

//如果去掉mutating则编译无法通过


结构体:当你不设置初始化函数时候,会默认得到一个将所有属性作为参数的初始化方法,例如:

struct MyStruct {

var x:Int = 42

  var y:String = “moltuase”

init(x:Int, y: String) //默认初始化方法  

}

ps:结构体可以重写init,可以有多个init(参数列表要不同)



扩展:添加额外的方法(扩展后的方法或属性都是默认实现的)

格式 extension类型名 {

            //添加需要的方法或需要的额外属性

    }

例子:

extension Int {

      //额外的属性

    var doubled :Int {

        return self * 2

    }

// 额外的方法

    func everything () ->() {

        print("i am \(self)")

    }

}

//可另外创建一个swift文件,在该文件进行扩展

//使用的时候不要import该文件,会自动添加到每个该类型的对象实例中

//扩展还可以实现协议 



  //尾随闭包

    func someFuntion(firstName first:( str:String) -> String) ->String{

        

        var name = first(str: "book")

        return name

    }

使用:  var name  =  someFuntion { (str) -> String in

            return str+"Jo"

           }

          //name = bookJo

上式等同于   var name  =  someFuntion {

            return $0+"Jo"

           }


 提示:如果函数的 body只有一行,则可以把 return 关键字省略了


//匿名闭包

 let textLabel = {

                Void -> UILabel in

                let label =  UILabel.init(frame: CGRectMake(150, 80, 30,    40))

                label.textColor = UIColor.yellowColor()

                label.text = "text"

                view.addSubview(label)

                return label

            }()

等同于:

 let textLabel:UILabel = {

 let label =  UILabel.init(frame: CGRectMake(150, 80, 30,    40))

                label.textColor = UIColor.yellowColor()

                label.text = "text"

                view.addSubview(label)

                return label


}()

也等同于:

 let textLabel:UILabel {

 let label =  UILabel.init(frame: CGRectMake(150, 80, 30,    40))

                label.textColor = UIColor.yellowColor()

                label.text = "text"

                view.addSubview(label)

                return label

}

//隔离代码,并同时进行赋值,让代码更加简洁



    //函数返回函数

    func sumSet(var sum sum: Int) -> ( sum_: Int) -> Int {

        var all = 0

        func sumAdd( sum_: Int) -> Int {

    

    

         return all + sum_ + sum  //sumAdd的返回

    }  

    return sumAdd   //sumSet的返回   

 }

使用:  var  function = sumSet (10)  //int -> IntFunction

             var all = function (10)

           //all = 20



 柯里化(currying

   func someFuntion2(test: Int)( str:String) -> String {

        return "test:\(test), str:\(str)"

    }

使用:  let function = someFuntion2(1)

          //function 为一个string -> StringFunction

        let str = function(str: "2")

        //str


函数内修改 :inout

在方法/函数的参数声明时候使用关键字:inout,可是传入的参数在方法/函数内同步修改

例子:

    func someFuntion3( inout  test: String) -> () {

        test = test + "!!!!"

    }

     var str = "a"

        someFuntion3(&str)

//str此时等于a!!!!



默认参数

在类型声明后直接赋值

例子:

class Vector2D {

    var x: Int?

    var y: Int?

    init (x: Int = 5, y: Int = 5) {

        self.x = x

        self.y = y

    }

}

提示:当前有默认参数的时候,调用该方法的时候可以不写参数

例子:class MyClass {

   

    func testPrint(test1: String = "book", test:String = "test") {

        print("test = \(test1)")

        print("test = \(test)")

    }

}

let test = MyClass()

        test.testPrint()

//输出:test = book

test = test





单例

例子:

class MyManager {

    var num: Int?

    var sum: Int?

    private static let sharedInstance = MyManager()

    class var shareManager : MyManager {

        return sharedInstance

    }

}

使用:let manager = MyManager.shareManager

        manager.num = 10




获取对象类型 object_getClass()

例子:        var test = 1

        print("\(object_getClass(test))")   //__NSCFNumber



判断(比较)对象类型  is

例子: var test = 1

        if test is Int {

            print("yes")

        }

//yes


KVC

例子:

class MyClass:NSObject {

        dynamic var date = NSData()

    dynamic var num = 0

}

    private var myContext = 0

    var myObj: MyClass!

   

  override func viewDidLoad() {

        super.viewDidLoad()

        myObj = MyClass()

        myObj.addObserver(self, forKeyPath: "num", options: .New, context: &myContext)

        self.myObj.num = 1

        

    }


    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {

        print("触发该方法")

    }

//

//dynamic只能用于类成员,指明它们需要动态派发,此时才能使用kvc

//需要一个子类,继承自NSObjec(只有继承之NSObject的类才能使用kvc

//设置对应的key path(需要观察的成员名)



比较指针(内存地址是否相同),使用『===』,该操作符用于判断两个AnyObject是否为同一个引用

例子:

  var str1 = "a" as AnyObject

        var str2 = "a" as AnyObject

        if str1 === str2 {

            print("指针相等")

        }

        if str1.isEqual(str2){

            print("内容相等")

        }

//输出:内容相等


  var str1 = "a" as AnyObject

        var str2 = str1 as AnyObject

        if str1 === str2 {

            print("指针相等")

        }

        if str1.isEqual(str2){

            print("内容相等")

        }

//输出:指针相等

内容相等


//swift中,单纯比较内容是否相等,使用==即可,如果是NSObject类型,则使用isEqual





遍历数组 enumerate

例子:   let test = [1,"a",2,"b",3,4]

        for  (idx,num) in test.enumerate(){

            print((idx,num))

        }

//输出:(0, 1)

(1, a)

(2, 2)

(3, b)

(4, 3)

(5, 4)


为数组元素添加新的东西:map

例子: let name = ["1","2","3","4"]

        let member = name.map{

               "成员" + $0

        }

//["成员1", "成员2", "成员3", "成员4"]


对数组的元素按照某种规则增减: reduce

例子: let array = ["B","O","O","K"]

        let brr = array.reduce("Jo"){

            print("$0:\($0)")

            print("$1:\($1)")

            print("________")

            return $0 + $1

        }

        print("brr :\(brr)")

输出: 

$0:Jo

$1:B

________

$0:JoB

$1:O

________

$0:JoBO

$1:O

________

$0:JoBOO

$1:K

________

brr :JoBOOK


例子2

let arr = [1, 2, 4]

// arr = [1, 2, 4]

let crr = arr.reduce("") {

    if $0 == "" {

        return String($1)

    } else {

        return $0 + " " + String($1)

    }

}

// crr = "1 2 4"


按照一定规则进行筛选:filter

例子:let arr = [1, 2, 4]

// arr = [1, 2, 4]


let brr = arr.filter {

    $0 % 2 == 0

}

// brr = [2, 4]





加锁和解锁 lock

swift不存在@synchronized()的用法,但可以使用objc_sync_enter()objc_sync_exit()达到相同的效果

例子:

func mymethod(myObjc: AnyObject) {

    objc_sync_enter(myObjc)

    //enterexit之间myObjc不会被其他线程改变

    objc_sync_exit(myObjc)

}



随机数生成 arc4random_uniform(_:UInt32) ->UInt32

例子: let dicefacecount: UInt32 = 6

        var test = Int(arc4random_uniform(dicefacecount))

        print(test)

//生成0~5的数字

//不使用arc4random,因为在苹果5或者以下设备中,有时候会崩溃,请注意!是『有时候』!

//最佳实践如下:

    func randomInRange(range: Range<Int>) -> Int {

        let count = UInt32(range.endIndex-range.startIndex)

        return Int(arc4random_uniform(count)) + range.startIndex

    }

使用:   print(randomInRange(1...6)) //输出1~6的任一数字




错误(报错)提醒 fatalError

抛出错误,显示提示信息或者注意信息

例子:

class BaseClass {

    func baseMethod() {

        fatalError("basemethod必须要重写")

    }

}

class YourClass: BaseClass {

    override func baseMethod() {

        print("重写了")

    }

}

class ThisClass: BaseClass {

    

}

使用:      let test = YourClass()

        test.baseMethod()

        let test1 = ThisClass()

        test1.baseMethod()   //在此处崩溃

 


操作符 『??』,如果??左侧表达式的值不为nil,则使用左侧表达式的值,若为nil,则使用右侧表达式的值。

例子:

let value =  self.array ?? self.dictionary 


范型

例子:func funcBuild<T, U, V>(f: T -> U, _ g: V -> T)

    -> V -> U {

        return {

            f(g($0))

        }

}

let f3 = funcBuild({ "No." + String($0) }, {$0 * 2})

f3(23) // 结果是 "No.46"


func myFunc<T,U> ( first: T, second: U) -> U {

        print("first :\(first)")

        let myRet: U = second

        return myRet

    }

        let fitst = ["name" : "name"]

        let second = [1,2,3]

        let myStr = self.myFunc(fitst, second: second)

        print("str: \(myStr)")

//输出: first :["name": "name"]

str: [1, 2, 3]



swift规范写法:

例子:if n.isNumber {

    // Use n here

} else {

    return

}

改成:

guard n.isNumber else {

    return

}

// Use n here



使用闭包函数初始化成员时,如要在闭包函数中使用类成员,需要在声明的成员加上lazy

例子:

   lazy var centerButton: CenterButton = {

        let button: CenterButton = CenterButton.init(frame: CGRectMake(0, 0, self.centerButtonSize!.width, self.centerButtonSize!.height), type: self.centerIconType!)

        return button

    }()




避免循环引用: 引用的代码前面添加 [weak self] in

eg

class TestClass {

    var name: String?

    lazy var printName: () -> () = {

        [weak self]  in

         print("\(self!.name)")

    }

    init(name: String) {

        self.name = name

    }

    deinit {

        print("name:\(self.name) deinit");

    }

}

使用:

   test = TestClass(name: "book");

        test?.printName()

        test = nil

输出:

Optional("book")

name:Optional("book") deinit


限制扩展,关键字: where self: protocol

例子: 

protocol Jo {

    var name: String { get set}

}

protocol EnglishName {

    var egName: String {get set}

}

extension EnglishName where Self: Jo {

    func printNmae() -> () {

        print("name: \(self.name)")

    }

  

}

struct Test: EnglishName, Jo {

    var name: String

    var egName: String

}

//输出:name: Jo

//只有继承Jo,才有printNmae函数


判断对象是否为空,可以使用赋值创建的方式,例如:

 if let image = UIImage(named: “foo”)

 { // image 如果创建成功,走这里

} else 

{ // 如果不存在foo图片,创建失败,则走这里

}

或者:

var dic: Dictionary<String,String>?

 if let dic2 = dic {

            print("??")

        } else {

            print("!!!")

        }

输出:”??”


关键字:@IBDesignable@IBInspectable,可以支持实时渲染到界面,注意必须是UIView或者NSView的子类

例子:

import UIKit

@IBDesignable

class TestView: UIView {

     var testBtn: UIButton = UIButton.init()

    @IBInspectable var btnColor: UIColor = UIColor.redColor()

    @IBInspectable var btnFrame: CGRect = CGRectMake(50, 50, 100, 100)

   

    override func layoutSubviews() {

        super.layoutSubviews()

        self.testBtn.frame = btnFrame

        self.testBtn.backgroundColor = btnColor

    }

    override init(frame: CGRect) {

         super.init(frame: frame)

         self.testBtn.frame = btnFrame

         self.testBtn.backgroundColor = btnColor

        self.addSubview(self.testBtn)

    }


    required init?(coder aDecoder: NSCoder) {

        fatalError("init(coder:) has not been implemented")

    }

}


//提示:重写layoutSubviews(),并在其中加入对应IBInspectable声明的变量属性,才可以动态改变界面的效果


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值