swift基础(二)

懒加载

如果你用懒加载添加了一个属性,如果要主动释放该属性,使该属性=nil,这样是不行的,除非你在viewdidLoad中重新加载,这样一来就重复了,所以如果你要主动释放一些属性,那么这些属性就最好不要用lazy,如果你释放了这些属性但是VC并没有release掉的话,lazy属性不会重新加载

 // MARK: lazy
    lazy var rightItemButton: UIButton = {
        let btn = UIButton()
        btn.frame = CGRect(x: 10, y: 10, width: 40, height: 40)
        btn.setImage(UIImage(named: "image"), for: UIControlState.normal)
        btn.setImage(UIImage(named: "highlited_image"), for: UIControlState.normal)
        btn.setTitle("编辑", for: UIControlState.normal)
        btn.setTitleColor(UIColor.red, for: UIControlState.normal)
        btn.addTarget(self, action: #selector(leftEditItemAction(btn:)), for: UIControlEvents.touchUpInside)
        return btn
    }()

    lazy var leftItemButton: UIButton = {
       // swift中能不写self就不写self, 在闭包中必须写self
        $0.frame = CGRect(x: 10, y: 10, width: 40, height: 40)
        $0.setImage(UIImage(named: "image"), for: UIControlState.normal)
        $0.setImage(UIImage(named: "highlited_image"), for: UIControlState.normal)
        $0.setTitle("保存", for: UIControlState.normal)
        $0.setTitleColor(UIColor.red, for: UIControlState.normal)
        $0.addTarget(self, action: #selector(rightSaveItemAction(btn:)), for: UIControlEvents.touchUpInside)

        return $0
    }(UIButton())

    //必须判断数组是否为空 然后进行加载,否则当数组为空的时候,不会重新进行加载
    lazy var dataArray: NSMutableArray? = {
       let array = NSMutableArray()
        return array
    }()

给按钮添加点击事件

// MARK: Target Action
    //运行循环监听到事件后,向 VC 发送消息,动态执行 方法,因此不能设置为 private
    @objc func leftEditItemAction(btn: UIButton) {
        print("点击左上角-----编辑----按钮 \(btn)")
    }

    @objc func rightSaveItemAction(btn: UIButton) {
        print("点击右上角-----保存-----按钮 \(btn)")
    }

$0和$1

Swift 自动对行内闭包提供简写实际参数名,你也可以通过 0,1 , $2 等名字来引用闭包的实际参数值
可以用0、1、2来表示调用闭包中参数,0指代第一个参数,1指代第二个参数,2指代第三个参数,以此类推n+1指代第n个参数,后的数字代表参数的位置,一一对应。

 let numbers = [3, 4, 2, 1, 5, 6]
 let sortedNumbers = numbers.sorted(by:{$0 < $1})
 print(sortedNumbers)
//输出结果
[1, 2, 3, 4, 5, 6]

使用命名空间动态加载类

1、在swift中,类名的组成格式是 namespace.类名
2、namespace对应的是CFBundleExecutable
3、从mainBundle的inforDictionary获取命名空间名称

print("获取mainBundle----- \(Bundle.main.infoDictionary!)")
let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
print("获取命名空间--------- \(namespace)")

1、在swift中,类名是包含命名空间的
2、命名空间默认是项目名称,同一个命名空间全局共享
3、如果是新建项目,项目名称中含有中文,可以按照下修改
target->Build Settings-> Product Name->$(TARGET_NAME)
(不能有中文、不能以数字、—开头)

private func addVCAccordingClassName() {
        addChildVCAccordingClassName(vcName: "HomeViewController", title: "首页", imageName: "tabbar_home")
        addChildVCAccordingClassName(vcName: "MessageViewController", title: "消息", imageName: "tabbar_message_center")
        addChildVCAccordingClassName(vcName: "DiscoverViewController", title: "发现", imageName: "tabbar_discover")
        addChildVCAccordingClassName(vcName: "MineViewController", title: "我的", imageName: "tabbar_profile")
    }

    //根据类名,动态创建类
    private func addChildVCAccordingClassName(vcName: String, title: String, imageName: String) {

        tabBar.barTintColor = UIColor.orange

        let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
        let className = namespace + "." + vcName
        //告诉编译器暂时就是AnyClass
        let tmpClass: AnyClass! = NSClassFromString(className)
        //告诉编译器真实的类型是UIViewController
        let trulyClass = tmpClass as! UIViewController.Type

        //实例化控制器
        let viewController = trulyClass.init()
        viewController.title = title
        viewController.tabBarItem.image = UIImage(named: imageName)
        viewController.tabBarItem.selectedImage = UIImage(named: imageName + "_highlighted")
        let nav = UINavigationController(rootViewController: viewController)
//        let nav = UINavigationController()
//        nav.addChildViewController(viewController)
        addChildViewController(nav)
    }

正常加载子控制器

   //添加所有子控制器
    func addChildViewControllers() {
        initChildViewController(childController: HomeViewController(), title: "首页", imageName: "tabbar_home")
        initChildViewController(childController: MessageViewController(), title: "消息", imageName: "tabbar_message_center")
        initChildViewController(childController: DiscoverViewController(), title: "发现", imageName: "tabbar_discover")
        initChildViewController(childController: MineViewController(), title: "我的", imageName: "tabbar_profile")
    }
    //初始化子控制器
    func initChildViewController(childController: UIViewController, title: String, imageName: String) {

        //tabbar和nav都有
        childController.title = title
        childController.tabBarItem.image = UIImage(named: imageName)
        childController.tabBarItem.selectedImage = UIImage(named: imageName + "_highlighted")
        tabBar.tintColor = UIColor.orange

        //创建导航控制器
        let nav = UINavigationController()
        nav.addChildViewController(childController)
        //添加控制器到tabbarVC
        addChildViewController(nav)
        //跟踪类名称
        print("-------类名------------- \(childController)")
    }

下划线的用法

swift中下划线,可以用于忽略外部参数名,一般第一个参数的外部名是被自动忽略的 (外部参数名,也就是当你调用这个方法时,参数列表中:前面的参数

//用下划线前
func myFunc(name: String, age: Int, grade: Int) {
    print("未使用忽略符 -add: name = \(name), age = \(age), grade = \(grade)")
}
myFunc(name: "Bob", age: 23, grade: 33)
//myFunc(name: <#T##String#>, age: <#T##Int#>, grade: <#T##Int#>)

//使用下划线后 忽略外部方法名
func myFunc2(_ name: String, _ age: Int, _ grade: Int) {
    print("使用忽略符后 -add: name = \(name), age = \(age), grade = \(grade)")
}
myFunc2("Li", 22, 12)
//myFunc2(<#T##name: String##String#>, <#T##age: Int##Int#>, <#T##grade: Int##Int#>)

闭包

函数式闭包的一种 类似于OC语言的block 闭包表达式(匿名函数)–能够捕获上下文中的值

语法:in 关键字的目的是便于区分返回值和执行语句
闭包表达式的类型和函数类型一样,是参数加上返回值,也就是in之前的部分,之后的部分是函数体
{
(参数) -> 返回值类型 in
执行语句
}


//方式一 利用typealias完整写法
typealias Add = (_ num1: Int, _ num2: Int) -> (Int)
//创建一个Add类型的闭包常量 addCloser1
let addCloser1: Add
//为已经创建好的常量 addCloser1 赋值
addCloser1 = {
    (_ num1: Int, _ num2: Int) -> (Int) in
    return num1 + num2
}

//调用闭包 并接受返回值
let result = addCloser1(34, 44)
print("方式一写法- 返回值 \(result)")

//方式二 闭包类型声明和变量的创建合并在一起
let addCloser2:(_ num1: Int, _ num2: Int) -> (Int)
addCloser2 = {
    (num3: Int, num4: Int) -> (Int) in
    return num3 + num4
}

let result2 = addCloser2(12, 1)
print("方式二写法- 返回值 = \(result2)")

//完整写法 返回值为空
let sayHello:(String) -> Void = {
    (name: String) -> Void in
    print("打招呼  \(name)")
}
sayHello("\("你好呀")")

//有返回值 有参数
let speakHello:(_ isMan: Bool, _ moneyNum: Double) -> Bool = {
    (_ isMan: Bool, _ moneyNum: Double) -> Bool in
    var change: Bool
    if isMan == true && moneyNum >= 100 {
        change = true
    } else {
        change = false
    }
    print("有返回值有参数\(change)")
    return change
}
speakHello(false, 100)

//没有返回值 没有参数
let noParam:() -> Void = {
    print("无返回值无参数")
}
noParam()

闭包表达式作为回调函数

func showArray(array:[Int]) {
    for number in array {
        print("闭包表达式作为回调函数=\(number)")
    }
}

showArray(array: [1, 4, 6, 90, 4])

let cmp = {
    (a: Int, b: Int) -> Int in
    if a > b {
        return 1
    } else if a < b {
        return -1
    } else {
        return 0
    }
}

// inout 地址 指针
func bubbleSortArray(array:inout [Int], cmp:(_ num1: Int, _ num2: Int) -> Int) {
    let count: Int = array.count
    for i in 0 ..< count {
        if i < count - 1 {
            if cmp(array[i], array[i + 1]) == -1 {
                let tmp = array[i]
                array[i] = array[i + 1]
                array[i + 1] = tmp
            }
            print("---\(i)---")
        }
    }
    print("闭包表达式作为回调函数---- \(array)")
}

var arr:Array = [34, 21, 56, 789, 90, 11, 2, 4]
bubbleSortArray(array: &arr, cmp: cmp)

var str1:String = "fsdf"
//bubbleSortArray(array: &str1, cmp: cmp)

//var dic:[String : Any] = ["key1": "value1", "key2": "value2", "key3": "value3"]
//bubbleSortArray(array: &dic, cmp: cmp)

如果闭包是最后一个参数,可以直接将闭包写到参数列表后面
swift可以使用$索引的方式来访问闭包的参数,默认从0开始

闭包捕获值

func getIncFunc(inc: Int) -> (Int) -> Int {
    var max = 10

    func incFunc(x: Int) -> Int {
        print("incFunc函数结束")
        max += 1
        return max + x
    }
    //当执行到这一句时inc参数就应该被释放了但是由于在内部函数中使用到了他,所以他被捕获了
    //同理,当执行完这一句时max变量就被释放了,但是由于在内部函数中使用到了他,所以他被捕获了
    print("gfetIncFunc函数结束")
    return incFunc
}

//被捕获的值会和与之对应的方法绑定在一起,同一个方法中的变量会被绑定到不同的方法中
let incFunc = getIncFunc(inc: 5)
print(incFunc(5))
let incFunc2 = getIncFunc(inc: 5)
print(incFunc2(6))

你可能感兴趣的:(Swift学习)