I have a view controller that has a private NSArray
variable. The variable is initialised in the viewDidLoad
method. A few questions arise for the case when the didReceiveMemoryWarning
is called:
我有一个具有私有NSArray变量的视图控制器。该变量在viewDidLoad方法中初始化。调用didReceiveMemoryWarning时会出现一些问题:
- Should I set the private variable to
nil
? - If I set it to
nil
in what method must it be recreated? Does the view controller call theviewDidLoad
method to recreate it?
我应该将私有变量设置为nil吗?
如果我将它设置为nil,必须重新创建哪种方法?视图控制器是否调用viewDidLoad方法来重新创建它?
I'm asking because other methods of the view need this variable and won't work if it's nil
.
我问,因为视图的其他方法需要这个变量,如果它是零则无法工作。
Thank you!
5 个解决方案
#1
-2
Its better to set your variable to nil. I mean release the memory it is holding in didReceiveMemoryWarning
and set a dirty flag.
最好将变量设置为nil。我的意思是释放它在didReceiveMemoryWarning中保存的内存并设置脏标志。
You can always check the dirty flag in array's getter(you can write your own) and repopulate it. It is probably not the best way. It entirely depends on the array's usage.
你总是可以检查数组getter中的脏标志(你可以自己编写)并重新填充它。这可能不是最好的方式。它完全取决于阵列的用法。
#2
4
Typically you unload a private property by assigning nil
via the setter (e.g. self.propertyName = nil
). Or you could set the ivar to nil after calling release, e.g. [_propertyName release]; _propertyName = nil;
, but the former is preferable.
通常,您通过setter分配nil来卸载私有属性(例如self.propertyName = nil)。或者你可以在调用release后将ivar设置为nil,例如[_propertyName release]; _propertyName = nil;,但前者更可取。
The didReceiveMemoryWarning
method is called when there is a low memory situation. It is called on every view controller, including the one(s) responsible for the currently visible UI!
当内存不足时调用didReceiveMemoryWarning方法。它在每个视图控制器上调用,包括负责当前可见UI的一个(!)!
Therefore, you can't just unload data arbitrarily when you get a call to didReceiveMemoryWarning
-- the view controller might need that data if it is currently visible on the display.
因此,当您调用didReceiveMemoryWarning时,您不能随意卸载数据 - 视图控制器可能需要该数据(如果它当前在显示器上可见)。
The general principle is that didReceiveMemoryWarning
can get rid of any resources it can to assist freeing up memory, but only those that aren't immediately needed. For example, in an OpenGL game you wouldn't unload textures that are currently visible on the display. However, see my last paragraph.
一般原则是didReceiveMemoryWarning可以摆脱它可以帮助释放内存的任何资源,但只有那些不是立即需要的资源。例如,在OpenGL游戏中,您不会卸载当前在显示器上可见的纹理。但是,请参阅我的最后一段。
Typically you reload the resources by checking they are loaded when you need them, and if not, loading them.
通常,您可以通过在需要时检查它们是否已加载来重新加载资源,如果没有,则加载它们。
It's not worth niling/releasing tiny resources such as a single normally sized string. You should concentrate on items taking up significant amounts of memory.
不值得捏造/释放微小资源,例如单个正常大小的字符串。你应该专注于占用大量内存的物品。
Recent advances in behind the scenes memory management mean you're less likely to need to actually unload data these days - the operating system can unload and reload uncompressed image data and the like behind the scenes.
幕后内存管理的最新进展意味着您现在不太可能需要实际卸载数据 - 操作系统可以在后台卸载和重新加载未压缩的图像数据等。
As Hot Licks mentions, the simulator has an option for simulating a memory warning. It's worth triggering this memory warning at various points in your app to see how it behaves.
正如Hot Licks所提到的,模拟器有一个模拟内存警告的选项。值得在应用程序的各个点触发此内存警告以查看其行为方式。
#3
1
Create custom getter that load data lazily. Something such as this snippet is good for non-mutithreading eviroment:
创建懒惰加载数据的自定义getter。像这个片段这样的东西对于非多线程的解释是有益的:
- (NSArray*) dataArray {
if(_dataArray) return _dataArray;
_dataArray = [self lordata];
return _dataArray;
}
In this way data are always reloaded if you "release" them in memory warnings
这样,如果您在内存警告中“释放”数据,则始终会重新加载数据
#4
0
The ViewDidLoad
method is called only once, when your ViewController is initialized. If you must reload some data to your NSArray, you should call your own methods to do that when needed.
初始化ViewController时,只调用一次ViewDidLoad方法。如果必须将某些数据重新加载到NSArray,则应在需要时调用自己的方法来执行此操作。
If this array is used by various parts of the code, maybe you should think about redesigning your code structure to avoid a huge concentration of data inside only one object.
如果代码的各个部分使用了这个数组,那么你应该考虑重新设计代码结构,以避免仅在一个对象中集中大量数据。
Edit: As pointed by @occulus in the comments below, it is not called when the View is initialized, but when the View is loaded by the ViewController.. my mistake
编辑:正如@occulus在下面的评论中指出的那样,在View初始化时没有调用它,但是当ViewController加载了View时..我的错误
#5
0
As an example, I had an app that downloaded data to a very long table view (potentially 1000s of records). To support this I implemented a "sparse" array, allowing empty elements that would be "faulted in" over the net when referenced (with a "downloading" indicator in the table cell while downloading).
作为一个例子,我有一个应用程序将数据下载到一个非常长的表视图(可能是1000个记录)。为了支持这一点,我实现了一个“稀疏”数组,允许在引用时通过网络“故障”的空元素(在下载时使用表格单元格中的“下载”指示符)。
This was rigged so that when didReceiveMemoryWarning occurred the array would be purged, using a least-recently-used algorithm to delete the oldest N% of the array. Recovery would be automatic -- the emptied cells would reload when they were referenced.
这被操纵,以便当didReceiveMemoryWarning发生时,将使用最近最少使用的算法清除数组,以删除最旧的N%数组。恢复将是自动的 - 清空的单元格在被引用时会重新加载。
Not that I recommend this specific scheme, but note the general features of having a lot of data, having a way to "prioritize" what should be deleted, and having a "soft" way to reload the data (ideally only reloading the parts that are needed in the near future).
不是我推荐这个特定的方案,而是注意拥有大量数据的一般特征,有一种方法可以“优先”应该删除的内容,并且有一种“软”方式来重新加载数据(理想情况下只重新加载那些部分)在不久的将来需要)。
#1
-2
Its better to set your variable to nil. I mean release the memory it is holding in didReceiveMemoryWarning
and set a dirty flag.
最好将变量设置为nil。我的意思是释放它在didReceiveMemoryWarning中保存的内存并设置脏标志。
You can always check the dirty flag in array's getter(you can write your own) and repopulate it. It is probably not the best way. It entirely depends on the array's usage.
你总是可以检查数组getter中的脏标志(你可以自己编写)并重新填充它。这可能不是最好的方式。它完全取决于阵列的用法。
#2
4
Typically you unload a private property by assigning nil
via the setter (e.g. self.propertyName = nil
). Or you could set the ivar to nil after calling release, e.g. [_propertyName release]; _propertyName = nil;
, but the former is preferable.
通常,您通过setter分配nil来卸载私有属性(例如self.propertyName = nil)。或者你可以在调用release后将ivar设置为nil,例如[_propertyName release]; _propertyName = nil;,但前者更可取。
The didReceiveMemoryWarning
method is called when there is a low memory situation. It is called on every view controller, including the one(s) responsible for the currently visible UI!
当内存不足时调用didReceiveMemoryWarning方法。它在每个视图控制器上调用,包括负责当前可见UI的一个(!)!
Therefore, you can't just unload data arbitrarily when you get a call to didReceiveMemoryWarning
-- the view controller might need that data if it is currently visible on the display.
因此,当您调用didReceiveMemoryWarning时,您不能随意卸载数据 - 视图控制器可能需要该数据(如果它当前在显示器上可见)。
The general principle is that didReceiveMemoryWarning
can get rid of any resources it can to assist freeing up memory, but only those that aren't immediately needed. For example, in an OpenGL game you wouldn't unload textures that are currently visible on the display. However, see my last paragraph.
一般原则是didReceiveMemoryWarning可以摆脱它可以帮助释放内存的任何资源,但只有那些不是立即需要的资源。例如,在OpenGL游戏中,您不会卸载当前在显示器上可见的纹理。但是,请参阅我的最后一段。
Typically you reload the resources by checking they are loaded when you need them, and if not, loading them.
通常,您可以通过在需要时检查它们是否已加载来重新加载资源,如果没有,则加载它们。
It's not worth niling/releasing tiny resources such as a single normally sized string. You should concentrate on items taking up significant amounts of memory.
不值得捏造/释放微小资源,例如单个正常大小的字符串。你应该专注于占用大量内存的物品。
Recent advances in behind the scenes memory management mean you're less likely to need to actually unload data these days - the operating system can unload and reload uncompressed image data and the like behind the scenes.
幕后内存管理的最新进展意味着您现在不太可能需要实际卸载数据 - 操作系统可以在后台卸载和重新加载未压缩的图像数据等。
As Hot Licks mentions, the simulator has an option for simulating a memory warning. It's worth triggering this memory warning at various points in your app to see how it behaves.
正如Hot Licks所提到的,模拟器有一个模拟内存警告的选项。值得在应用程序的各个点触发此内存警告以查看其行为方式。
#3
1
Create custom getter that load data lazily. Something such as this snippet is good for non-mutithreading eviroment:
创建懒惰加载数据的自定义getter。像这个片段这样的东西对于非多线程的解释是有益的:
- (NSArray*) dataArray {
if(_dataArray) return _dataArray;
_dataArray = [self lordata];
return _dataArray;
}
In this way data are always reloaded if you "release" them in memory warnings
这样,如果您在内存警告中“释放”数据,则始终会重新加载数据
#4
0
The ViewDidLoad
method is called only once, when your ViewController is initialized. If you must reload some data to your NSArray, you should call your own methods to do that when needed.
初始化ViewController时,只调用一次ViewDidLoad方法。如果必须将某些数据重新加载到NSArray,则应在需要时调用自己的方法来执行此操作。
If this array is used by various parts of the code, maybe you should think about redesigning your code structure to avoid a huge concentration of data inside only one object.
如果代码的各个部分使用了这个数组,那么你应该考虑重新设计代码结构,以避免仅在一个对象中集中大量数据。
Edit: As pointed by @occulus in the comments below, it is not called when the View is initialized, but when the View is loaded by the ViewController.. my mistake
编辑:正如@occulus在下面的评论中指出的那样,在View初始化时没有调用它,但是当ViewController加载了View时..我的错误
#5
0
As an example, I had an app that downloaded data to a very long table view (potentially 1000s of records). To support this I implemented a "sparse" array, allowing empty elements that would be "faulted in" over the net when referenced (with a "downloading" indicator in the table cell while downloading).
作为一个例子,我有一个应用程序将数据下载到一个非常长的表视图(可能是1000个记录)。为了支持这一点,我实现了一个“稀疏”数组,允许在引用时通过网络“故障”的空元素(在下载时使用表格单元格中的“下载”指示符)。
This was rigged so that when didReceiveMemoryWarning occurred the array would be purged, using a least-recently-used algorithm to delete the oldest N% of the array. Recovery would be automatic -- the emptied cells would reload when they were referenced.
这被操纵,以便当didReceiveMemoryWarning发生时,将使用最近最少使用的算法清除数组,以删除最旧的N%数组。恢复将是自动的 - 清空的单元格在被引用时会重新加载。
Not that I recommend this specific scheme, but note the general features of having a lot of data, having a way to "prioritize" what should be deleted, and having a "soft" way to reload the data (ideally only reloading the parts that are needed in the near future).
不是我推荐这个特定的方案,而是注意拥有大量数据的一般特征,有一种方法可以“优先”应该删除的内容,并且有一种“软”方式来重新加载数据(理想情况下只重新加载那些部分)在不久的将来需要)。