Chapter 6 : Delegation和Debug - The Big Nerd Ranch Guide 读书笔记

来源:互联网 发布:游戏编程入门 csdn 编辑:程序博客网 时间:2024/04/30 23:37

UIResponder

UIResponder是UIKit的一个抽象类。定义了处理event的方法:比如,touch event,motion event(摇动),还有remote control event(暂停和开始播放)。
当touch event发生的时候,会观察到user触摸了哪一个view,touch event会直接送到那个view。
对于其他类型的event,UIWindow有一个指针叫firstResponder,firstResponder暗示应该相应哪种类型的event。比如: 当你选择了一个text field,window会把它的firstResponder指针移到text field。键盘显示出来,当text field失去firstResponder,键盘隐藏。你如果想要某个view成为firstResponder,那个view调用becomefirstResponder消息。如果想隐藏键盘,调用resignFirstResponder

Debug

1. Exception

如果你想当你的程序的有任何异常,导致发生crash的时候,断点自动在任意一行停下。你可以做一个Exception断点:
这里写图片描述

Exception可以编辑,右键:
这里写图片描述
至于你的断点是on throw还是on catch,你可以根据crash的打印来看:
这里写图片描述

然后,在程序调用栈里面找到objc_exception_throw,选中。
然后,你可以把他的第一个参数用po打印出来,这个就是exception的原因:

(lldb) po $arg1(lldb) po [$arg1 name](lldb) po [$arg1 reason]

你可以把po $arg1加到exception的属性里面,然后以后就可以自动执行了:
这里写图片描述

2. Debug View runtime

当程序运行的时候,你可以看View的各个组件的关系:
这里写图片描述
按最下面的2个叠起来的方形的button

3 编辑break

这里写图片描述
如果你有一个循环100次的函数,你可以设定在在10次的时候停下来,然后打印log到console上。

4. addressing Sanitizer

t.b.d

main 和 UIApplication

一个C程序的开始执行点是main函数,iOS程序也一样。在以前的iOS程序有一个main.m 的文件。用UIApplicationMain创建了一个UIApplication的实例,每一个app,各有一个UIApplication的实例。这个实例维持了一个run loop。一旦这个实例创建,这个run loop就变成了一个无限循环。其次,UIApplicationMain创建了一个AppDelegate,并设置它为UIApplication的delegate。第一个添加到这个run loop的Event是通过didFinishLaunchingWithOptions这个message来传递的。

Delegate

方法一

现在有2个view controller,需要用delegate通讯:

  • 要发送数据/要发送信息的view controller
    • 写一个protocol:
//如果想要有optional函数@objc protocol sendMessageDelegate:class {    func didReceivedMessage(message:String)    optional func willReceiveMessage(message: String)}//如果不需要optional函数protocol sendMessageDelegate:class {    func didReceivedMessage(message:String)}
 - 在类里面声明一个名为delegate变量,这个例子不会产生循环引用,不需要加weak来避免循环引用,类型为协议的名字;
class SenderViewController: UIViewController {    var delegate: sendMessageDelegate?
 - 在自己类的函数里面调用protocol声明的方法。把你需要传递的数据和信息,通过函数参数传递到protocol声明的方法. 要注意的是,当这个函数调用的时候,第二个view controller应该已经初始化了。一般在PrepeareForSegue的时候调用,但是这个时候,第二个view controller的UI部分,比如label/button也没有初始化。 - 在segue里面取得第二个view controller的handler,然后把它赋值给delegate变量。
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {        if segue.identifier == "toSender" {            if let vc = segue.destinationViewController as? ReceiverViewController {               self.delegate = vc               //对于optional的protocol函数,要加?,不需要再用respondsToSelector, ?已经帮你处理好了。               delegate?.willReceiveMessage?(label.text!)               delegate?.didReceivedMessage(label.text!)                    }                }    }
  • 在接收数据的view controller里
    • adopt这个协议
class ReceiverViewController: UIViewController, sendMessageDelegate {
 - 实现protocol的方法,通过函数参数取得另外一个view controller的数据。不要在这个方法里面调用UI的部分。
func didReceivedMessage(message: String) {        text = message    }

方法二

现在有2个view controller,需要用delegate通讯:

  • 要发送数据的view controller (VCA)
    声明一个叫delegate的闭包, 把要发送的数据作为参数传进去
var delegate:((sendToSecondVCData:[AnyObject])->())?

在需要传递数据的时候,调用这个闭包

delegate(data)
  • 在接收数据的view controller里
    给这个delegate赋值:
VCA.delegate = {data in print(\(data))}
0 0