如果你用懒加载添加了一个属性,如果要主动释放该属性,使该属性=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)")
}
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))