iOS优化内存,提升性能 之四

发布时间:2020-06-27 08:49:40 作者:iKingLai
来源:网络 阅读:554

UI中显示和隐藏view


UI中显示和隐藏view,需要用到的内存操作很少。但是,这个和iOS app的性能和用户体验有关。


view显示或隐藏时,在view controller中有4个主要的方法来表示view的不同状态。


§ viewWillAppear:在view显示之前会调用这个方法。只有这个方法调用完之后,才会显示你的view。为了给应用创造一个很好的用户体验,在这里做的计算最好要非常的快。否则,用户会感觉你的导航和动画比较弱。一个好的做法是设置view的属性(例如,背景色或文本颜色)。


例如,用户按下返回按钮返回到view A。但是,在view A的viewDidAppear方法内部,有一个耗时的计算。这个计算结果可能会花几秒钟,但是同时UI线程会被阻塞来处理view A的内部逻辑,同时view A也无法显示。



例如,你有一个排序算法来对你的table view进行排序。当用户看到view A时,旧的table还在显示。然后突然所有的的rows发生了变化,而没有任何的警告或是解释发生了什么事情。



没有什么硬性规则说你应该把逻辑处理过程放在什么地方。我向你介绍了所有的基本的概念,你可以使用他们创建比较好的用户体验和性能。



对象拷贝


你为什么需要知道对象拷贝以及为什么需要它呢?拷贝一个对象是非常有用的,如果你不想改变旧的对象,因为它可能影响到其他部分程序。在某些情况下,你根本不能修改对象,所以你只能拷贝这个对象的内容,然后再进行修改。


浅拷贝和深拷贝


在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 {

  1. NSString *itemName;

  2. CGFloat price;
    id delegate;

}

@property (nonatomic, copy) NSString *itemName;

@property (nonatomic, weak) CGFloat price;

@property (nonatomic, weak) id delegate;


@end


在这个例子中,你可以看到有3个实例变量。第一个是itemName(这是一个指针对象),第二个是一个基本数据类型,第三个是一个delegate。


iOS优化内存,提升性能 之四

如图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对象。







推荐阅读:
  1. MYSQL(四)查询性能优化
  2. Oracle 学习之 性能优化(十四) 内存

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

ios 性能优化

上一篇:调用python下载文件

下一篇:python爬取主播信息

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》