重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
在UI中显示和隐藏view
创新互联主要从事网站设计、网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务遂宁,十年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18980820575
在UI中显示和隐藏view,需要用到的内存操作很少。但是,这个和iOS app的性能和用户体验有关。
当view显示或隐藏时,在view controller中有4个主要的方法来表示view的不同状态。
§viewWillAppear:在view显示之前会调用这个方法。只有这个方法调用完之后,才会显示你的view。为了给应用创造一个很好的用户体验,在这里做的计算最好要非常的快。否则,用户会感觉你的导航和动画比较弱。一个好的做法是设置view的属性(例如,背景色或文本颜色)。
例如,用户按下返回按钮返回到view A。但是,在view A的viewDidAppear方法内部,有一个耗时的计算。这个计算结果可能会花几秒钟,但是同时UI线程会被阻塞来处理view A的内部逻辑,同时view A也无法显示。
viewDidAppear:在view显示之后,这个方法会被调用,所以你可以把你的逻辑处理放在这里。但是,如果在它执行完后,你的处理过程会改变view,用户可能会感到迷惑,这不是一个好的用户体验。
例如,你有一个排序算法来对你的table view进行排序。当用户看到view A时,旧的table还在显示。然后突然所有的的rows发生了变化,而没有任何的警告或是解释发生了什么事情。
viewDidDisappear:在view从UI消失之前会调用这个方法。任何属于这个view的,你想要显示给用户的,都应该放在这里。注意在这里你不应该放置太多逻辑处理的代码。如果你在这里放了很多的逻辑处理代码,那么显示一个新的view就会花很多时间。
没有什么硬性规则说你应该把逻辑处理过程放在什么地方。我向你介绍了所有的基本的概念,你可以使用他们创建比较好的用户体验和性能。
对象拷贝
你为什么需要知道对象拷贝以及为什么需要它呢?拷贝一个对象是非常有用的,如果你不想改变旧的对象,因为它可能影响到其他部分程序。在某些情况下,你根本不能修改对象,所以你只能拷贝这个对象的内容,然后再进行修改。
浅拷贝和深拷贝
在Objective-C中,浅拷贝实际上和retaining是一样的。因为浅拷贝是拷贝一个对象的指针到一个新的变量中,在浅拷贝和retaining之间是没有什么不同的。
另一方面,深拷贝意味着你会实际创建一个新的对象,然后从旧的对象中拷贝所有的数据和实例变量到新的对象中。
为了演示浅拷贝和深拷贝在Objective-C之间的不同,考虑下面的代码:
Shallow copying:
- (void)setMyObj:(NSObject *)newObj {
if (newObj != myObj) {
myObj = newObj;
}
}
Deep copying:
- (void)setMyObj:(NSObject *)newObj {
if (newObj != myObj) {
myObj = [newObj copy];
}
}
在第一种情况下,你把变量的值赋值给一个新的对象然后retain这个对象。在Objective-C中,这就是浅拷贝。在深拷贝例子中,代码实际上拷贝了newObj的值和实例变量到myObj。
实现一个深拷贝
如果你确实需要一个深拷贝,你必须了解对象的整个层次结构。
你需要创建一个新的对象。
把旧对象的所有的实例变量拷贝到新对象中。
如果实例变量是基本数据类型,比如float,int或double,你只需要拷贝他们的值。Boolean不是基本类型,但是你也只需要拷贝它的值即可。
对于每一个指针类型的实例变量,你同样要拷贝它们的实例变量。
这个过程需要一直持续,直到结束。
这个过程可能很长,而且很难实现。一些内置的对象和库不支持深拷贝。因此,你需要在浅拷贝和深拷贝之间进行比较。例如,你不想深拷贝一个delegate,像前面介绍的,它会导致循环引用,即对象A拥有对象B,对象B拥有对象A。更进一步的,你通常不应该拷贝你的delegate,因为你最终只是想要回调它,而不是创建它。
这是一个混合了浅拷贝和深拷贝的例子:
@interface Item : NSObject {
NSString *itemName;
CGFloat price;
id delegate;
}
@property (nonatomic, copy) NSString *itemName;
@property (nonatomic, weak) CGFloat price;
@property (nonatomic, weak) id delegate;
@end
在这个例子中,你可以看到有3个实例变量。第一个是itemName(这是一个指针对象),第二个是一个基本数据类型,第三个是一个delegate。
如图7-8,delegate对象在原始的item和新的item中将保持一样。itemName对象将会被拷贝,有一个新的内存地址(0x9124代替了0x8028),但是都有同样的值“egg”。对于基本数据类型,例如price,将会被拷贝,它没有内存地址。
在对象中实现copy方法
为了实现对象的深拷贝,你通常需要重写copyWithZone:方法。当向一个对象发送copy消息,这个方法会被调用。这里有一些重写这个方法的代码。你需要用alloc和init创建一个新的对象,然后使用set方法给实例变量设值。
- (id)copyWithZone:(NSZone *)zone {
Item *copy = [[Item allocWithZone: zone] initWithName:self.itemName];
copy.price = self.price;
copy.delegate = self.delegate;
return copy;
}
就像前面所说的,在你的item class中如果有自定义的实例变量,你需要为它实现copy方法。在我的例子中,为了简单起见,代码没有创建一个新的itemName对象。