由于大楼停电检修,今天公司聚餐,这两天的学习强度很到,和感谢头一直在耐心的教我们,给我们讲解。废话不多说
本次demo的重点:
1.左滑删除tableview里面的cell
2.观察者模式进行多页面传值
3.导航(A-B-C-A)注意内存问题,防止循环引用,不能在c-A的传递过程中,重新创建A页面,然后再进入页面
下面问题:
1.delegate模式和NSNotification监听者模式都是基于消息回调的一种方式,那么delegate和NSNotification最大的区别是什么?
在ios之基础上的设计模式里代理模式就是delegate模式,由于当时看书,没实践,今天做题竟然不知道是代理模式,现在才知道,代码是要多练多熟悉才好,你爱它越深,它回馈给你的越多。
delegate模式都是单播,NSNotification是多播可以有多个监听者。
delegate是基于继承的,而NSNotification是基于对象组合的,都可用于页面传值
delegate就是java中基于接口的回调
[NSNotificationCenter defaultCenter]postNotificationName:@"sum" object:self]
这段代码是触发消息代码
NSNotificationCenter *nc=[NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(chaneNum:)name:@"sum" object:nil];
这里是注册监听事件
-(void)chaneNum:(NSNotification *)notification{.text=[notification object];
self.UILable
}
我们首先看发送消息的代码:postNotificationName方式
- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSString *)aName object:(id)anObject;
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
它有三个重载方法
其中第二个和第三个方法其实就是通过参数,填充NSNotification结构,然后再调用第一个方法
<span style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);"></span><pre name="code" class="objc"><span style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);">@interface NSNotification : NSObject <NSCopying, NSCoding></span><br style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);" /><br style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);" /><span style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);">- (NSString *)name; //要监听的事件名称</span><br style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);" /><span style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);">- (id)object; //是谁发送的</span><br style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);" /><span style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);">- (NSDictionary *)userInfo;//他发送的时候还附加了哪些信息</span><br style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);" /><br style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);" /><span style="font-family: 微软雅黑, 'MS Sans Serif', sans-serif; font-size: 15px; background-color: rgb(255, 237, 196);">@end</span>
NSNotification结构有三个成员的变量:
Name:消息名称 ,只有感兴趣的消息,通过名称来确定,然后处理
object:消息的发送者,基本上你不填或者填self
userinfo是发送该消息时给更多的信息,你自己可以添加更多信息,用NSMutableDictionay,然后塞进去
object的类型是id表示一个interface对象的地址,用于标记事件的发送者。这个消息可以理解为事件:
事件有几个概念:
1.事件的发送者
2.事件信息
3.事件的接受者
4.事件的处理程序
object是指事件的发送者
事件的参数有两种方式
1.如果发送者有成员变量将数据传出去的话,就不需要用-(NSDictionary*)userInfo
2.如果发送者没有成员变量,并将数据传出去的话,就需要用-(NSDictionary*)userInfo创建一个NSMutableDictionary,然后将某个值或对象以valueForKey:(NSString *)方式塞进去
postNotification就是指明了事件的发送者以及事件相关的信息
通过object和userInfo这两个参数的详解到这里大家应该也就明白了吧
事件的发送者和事件信息都是postNotification中运用的
NSNotificationCenter *nc=[NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(chaneNum:)name:@"sum" object:nil];
addObserver这个函数中:第一个对象为self,说明接受者就是self这个ViewController,标明了事件的接受者
selector:@selector(chaneNum:)标明了事件处理handler
name标明了要监听的事件是哪个
最后一个object没什么用,基本上都是nil
-(void)chaneNum:(NSNotification *)notification{.text=[notification object];
self.UILable
}
消息处理,所有事件发送者的相关信息都是存放在NSNotification中
这是一种做法,下面让我们看另一种不合理的做法:
下面这种做法是无参数,是通过两个controller的owner指针指向页面的,它违背了监听者事件消息的用意,监听者事件消息这种机制要解决的就是耦合性,通过增加指针的方式,是根本不需要使用事件,如果增加owner指针的话,不能用strong,这样会导致循环引用。因为他是自引用的一种方式。
@property(strong,nonatomic)类*类名;
@interface UIPViewController:UIViewController<UITableViewDataSource,UItableViewDelegate>;
这种做法是UIPViewController继承了UIViewController,引用的类也继承了UIViewController,他们享有共同的基类,再一次强调了引用导致内存指针循环
会导致循环引用的两种情况是:双向引用和自引用。
现在我们要再postNotification的时候,将一个对象添加到一个字典中传出去
NSMutableDictionary *dictionary=[NSMutableDictionaru dictionaryWithObjectsAndKeys:[NSSting stringWithFormat:@"%d",self.count],@"value",nil];
[NSNotificationCenter defaultCenter]postNotificationName:@"sum" object:self userinfo:dic];
这里我们用的NSSting 因为我们值是一个int类型的
所以我们再改成这样:
NSMutableDictionary *dictionary=[NSMutableDictionaru dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:self.count],@"value",nil];
[NSNotificationCenter defaultCenter]postNotificationName:@"sum" object:self userinfo:dic];
我们之所以这样做因为这个和java以及C#一样,具有装箱和拆箱的概念
容器里面存储的类型必须是引用类型而不能是值类型
oc中不能自动装箱,必须要手动来做
从c++的角度来说,就是容器里存储的类型必须是分配在堆里面而不是栈里面
ios中值类型是哪些呢?
oc中各个接口的声明id类型是引用类型
凡是带*声明的都是引用类型
没有*声明的都是值类型
int long short float double char typedef出来的
xcode不能静态分配内存 一般NSArray * arr这样的都要加*
凡是Type t都是值类型
现在我们要新加一个功能,在第二第一个页面中,当第三个页面的计数器的值> 0时,进入第二或第一个页面时,显示一个等待的菊花,5秒钟后消失,用内置的等待控件
解决这个问题我们要熟悉controller的生命周期了
、init里不要出现创建view的代码。良好的设计,在init里应该只有相关数据的初始化,而且这些数据都是比较关键的数据。init里不要掉self.view,否则会导致viewcontroller创建view。
2、loadView中只初始化view,一般用于创建比较关键的view如tableViewController的tabView,UINavigationController的navgationBar,不可掉用view的getter(在掉super loadView前),最好也不要初始化一些非关键的view。如果你是从nib文件中创建的viewController在这里一定要首先调用super的loadView方法,但建议不要重载这个方法。
3、viewDidLoad 这时候view已经有了,最适合创建一些附加的view和控件了。有一点需要注意的是,viewDidLoad会调用多次(viewcontroller可能多次载入view,参见图2)。
4、viewWillAppear 这个一般在view被添加到superview之前,切换动画之前调用。在这里可以进行一些显示前的处理。比如键盘弹出,一些特殊的过程动画(比如状态条和navigationbar颜色)。
5、viewDidAppear 一般用于显示后,在切换动画后,如果有需要的操作,可以在这里加入相关代码。
6、viewDidUnload 这时候viewController的view已经是nil了。由于这一般发生在内存警告时,所以在这里你应该将那些不在显示的view释放了。比如你在viewcontroller的view上加了一个label,而且这个label是viewcontroller的属性,那么你要把这个属性设置成nil,以免占用不必要的内存,而这个label在viewDidLoad时会重新创建。--摘自点击打开链接
接下来我们要讲导航问题了
在完成80%的功能后,在审批界面是,要求既能导航到继续页面,也要导航到这页面,并且如果在程序运行中,如果发生网络连接错误,必须要跳转到登陆页面
有两种解决方法:
第一种是更改所有的控制器,涉及到修改所有的页面以及代码,从原来的UIViewController转变为继承自UINavigateController
第二种原来的界面和代码不变,在模态导航的基础上自己实现这里要求对生命周期有很好的了解。
今天问题说到这里,我要去查阅资料了