https://stablekernel.com/view-controller-in-ios-6/

Some of you may have noticed that your view controller in iOS 6 no longer gets sent to viewWillUnload or viewDidUnload. That’s because they don’t automatically unload their views anymore.

Your first thought may be, “Ok, well how do I manually unload my views on a low memory warning? This seems like a step backwards.”

Then you go searching for an answer, and you come up with this:

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if([self isViewLoaded] && ![[self view] window]) {
[self setView:nil];
}
}

However, this is both unnecessary and potentially harmful because of some changes to the underlying support for UIViews. Therefore, in practice, you rarely need to unload a view controller’s view during a low memory warning. (And in theory, you will never have to.)

But why? If you’ve read my entire iOS programming book, you’ve gained the knowledge that a UIView is a subclass of UIResponder (so that it can receive events) and has a pointer to its own CALayer instance (so that it can be drawn on the screen).

A CALayer is a container for a bitmap image. When a UIView runs its drawRect: method, it is creating the bitmap image for its layer. The rest of a layer’s instance variables (many of which it borrows from its UIView, like its frame and backgroundColor) indicate how and where that bitmap image is composited onto the screen.

But the biggest part of the layer (in terms of memory usage) is that bitmap. A layer itself is only 48 bytes and a standard UIView is only 96 bytes, regardless of their size on the screen. The memory consumption for a layer’s bitmap, however, grows very large depending on the bounds of the layer. For example, a full screen retina-display iPad view can be up to a whopping 12 megabytes.

The approach taken by iOS 6 is that a low memory warning should only destroy the layer’s bitmap, but keep the CALayer and UIView objects intact. This makes sense given the memory consumption of the view and layer are relatively small compared to the bitmap. Additionally, a bitmap can be redrawn by having the view run drawRect: again, so it is not like we’ve lost anything.

In fact, something is gained by this approach: your controller no longer needs to re-populate view content after a low memory warning. For example, consider a view controller that maintained a couple of text fields. If that view controller’s view were to go off screen and a low memory warning were to occur, the view controller must save the text currently in those text fields and repopulate them in viewDidLoad or viewWillAppear:. This is no longer an issue because the text fields are never destroyed, thus they retain their text for when the text field’s bitmap is drawn again. This simplifies a very error-prone section of UIViewController code.

There are some additional smarts built into this process of dumping the layer’s bitmap image that are really cool. First, let’s make sure we understand allocation and deallocation. When a memory is allocated (an object, a bitmap, whatever), an appropriately sized chunk of memory from the heap is marked as “in use” and a pointer to the beginning of that chunk of memory is returned. In the case of an object allocation, we think of that pointer as “the object” but really, it’s just the address of a chunk of “in use” memory.

While a chunk of memory is allocated (“in use”), there are guards that prevent code from using that memory unless it is accessed by going through the pointer that was returned during allocation. In a sense, that memory is safe from being screwed with unless you intend to screw with it.

Deallocation simply removes those guards and marks that chunk of memory as “not in use”. This means that the next time you allocate an object, you can use some or all of that “not in use” memory to form a new allocation. Upon deallocation, the values stored in that chunk of memory do not change. While it is possible to access that deallocated memory again and it may be the same, chances are that the memory has changed in some way. Therefore, it’s never safe to access deallocated memory through the pointer you were given upon allocation.

Now, on to why this matters for views and their layers. Each layer has a contents property that points to an object that represents the layer’s bitmap. The type of this object is a private, opaque class named CABackingStore, which contains the actual bitmap as well as some metadata (like whether or not the image has an alpha channel and how many bytes per pixel are used). Thus, it is the CABackingStore that needs to be destroyed when memory is running low.

However, the neat trick here is that a low memory warning does not destroy a CABackingStore. Instead, if a view is offscreen during a low memory warning, its layer’s CABackingStore is set to “volatile”. The volatile flag (which is not the same as the volatile keyword in C), in this context, is like deallocation in the sense that it allows the memory of the CABackingStore to be allocated for a different purpose. The difference between marking this memory as volatile and deallocating it is that the volatile memory can actually be reclaimed; it is not lost forever.

Consider why this is such an interesting optimization. If a view (more accurately, its layer) were to destroy its backing store, the next time the view went on screen it would have to recreate that backing store by running drawRect:. drawRect: is an expensive call, so avoiding it is very important. By allowing the backing store to be reclaimed, the layer can avoid having its UIView execute drawRect: again.

Of course, it is possible that some time between when the backing store was marked as volatile and the view that owned it goes back on the screen, the memory for that backing store was reallocated for a different purpose. In that case, the view would have to run its drawRect: method again to produce its bitmap.

JULY 12, 2013/BY JOE CONWAYTAGS: CALAYERIOS 6VIEW CONTROLLER

最新文章

  1. Docker初体验
  2. TListView列表拒绝添加重复信息
  3. ACM2032
  4. PCB的技巧
  5. [github] 创建个人网页
  6. 用qsort排序
  7. Java UML描述
  8. 模块化编程node
  9. htmldom操作添加标签顺序
  10. SignalR使用笔记
  11. Jdk 接口类RandomAccess了解
  12. Java虚拟机—垃圾收集器(整理版)
  13. Java8(1)之Lambda表达式初步与函数式接口
  14. python接口自动化28-requests-html爬虫框架
  15. SAC处理命令transfer的一些详细介绍
  16. Executor框架(一)
  17. java判断是移动端还是pc端
  18. 版本 ------- 2017年最受开发者欢迎的10个Linux发行版
  19. OC description和sel
  20. spring事务管理及相关知识

热门文章

  1. MCP|WJ|Identification of candidate plasma protein biomarkers for cervical cancer using the multiplex proximity extension assay(利用多重邻位延伸分析技术进行宫颈癌血浆蛋白候选生物标记物的鉴定研究)
  2. Java: 面向对象程序设计(下)
  3. ELK系列(4) - Elasticsearch cannot write xcontent for unknown value of type class java.math.BigDecimal
  4. java文件操作文件之csv
  5. java程序生成二维码
  6. ES6工作中常用知识点
  7. Luogu P2391 白雪皑皑 && BZOJ 2054: 疯狂的馒头 并查集
  8. 纯干货:Linux抓包命令集锦
  9. 自定义xml spring bean
  10. Domain Model