[英]memory not being released in iOS app using ARC
我用ARC建立了一個簡單的瑣事游戲。 在使用Xcode中的Allocations分析工具分析其內存使用情況時,我發現內存並不總是被釋放。 對於問題的一個示例,我有一個ActivePlayer對象的類:
ActivePlayer.h:
@interface ActivePlayer : NSObject
@property (nonatomic, strong) NSString * name;
@property (nonatomic) NSInteger overallScore;
@property (nonatomic) NSInteger questionScore;
- (id) initWithName:(NSString *)name;
@end
ActivePlayer.m:
#import "ActivePlayer.h"
@interface ActivePlayer ()
@end
@implementation ActivePlayer
- (id) initWithName:(NSString *)name
{
self = [self init];
if (self) {
self.name = name;
self.overallScore = 0;
}
return self;
}
/*
- (void)dealloc
{
self.name = nil;
}
*/
@end
ActivePlayer是在ActiveGame類的createPlayer方法中創建的:
[[ActivePlayer alloc] initWithName:name]
我正在執行以下測試用例:我開始一個新游戲(分配一個ActivePlayer),我回答一個問題,然后游戲結束(此時ActivePlayer被解除分配)。 然后我可以開始另一個游戲並重復這個循環(每個循環是一個“游戲”,如下所述)。 在使用Allocations性能分析工具時,我期望看到的是內存已經在游戲中分配,但在游戲結束后已經解除分配(無論我玩多少次游戲)。 但我發現情況並非總是這樣:
順便說一句:下面的每個項目符號行描述了“分配”工具的“對象列表”選項卡中的一行; 這個網站不會讓我發布截圖,因此文字描述。 所有行都是Live; 我只查看Created和Still Living分配。
雖然游戲#1正在進行中,但我看到以下分配。
比賽#1完成后,我看到以下內容。 ActivePlayer對象已被釋放,但48字節仍然是Live。
如果我開始游戲#2,我會在游戲進行過程中看到以下內容。 除了游戲#1中的一個之外,還有兩個新的分配。
在比賽#2完成后,我看到以下內容。 同樣,ActivePlayer對象已被解除分配,但“Malloc X Bytes”分配仍然存在。
在那之后,我得到了不尋常的結果 - 如果我玩游戲#3,#4和#5,我從來沒有看到Category =“Malloc X Bytes”的游戲內行,只有Category = ActivePlayer的新行,這是比賽結束后釋放。 如上所示,前兩個“Malloc”行繼續存在。 我還看到了其他奇怪的行為 - 在昨天使用iPhone 6.0模擬器進行測試時,實時內存僅在游戲#2和#3之后留下,但不是游戲#1,#4和#5。 因此,雖然內存仍然被分配,但它出現的時間似乎因我的設備和不同版本的模擬器而異。
我的問題是:
筆記:
您列出的代碼很好。 看起來您仍然在代碼中的其他位置維護對原始ActivePlayer的引用。
作為旁注,您創建ActivePlayer的模式不是常態 - 通常類不會在init方法中調用alloc。 相反,調用者應該執行:
[[ActivePlayer alloc] initWithName:@"Bob"];
並且你的init方法應該使用返回值
[super init];
我覺得很奇怪你的構造函數是靜態的(+符號)。 命名約定要求名稱前綴為init
將返回托管內存對象。 我懷疑內部方法的結果是根據其方法名稱進行評估的。
我認為實例計數測試確定您的代碼沒有泄漏ActivePlayers。 順便說一下,構造函數和inits上的更好的形式是這樣的:
// .h
@interface ActivePlayer : NSObject
+ (id)activePlayerWithName:(NSString *)name;
@end
// .m
+ (id)activePlayerWithName:(NSString *)name {
return [[self alloc] initWithName:name];
}
// if you want to make this public (include in .h interface) you can
// the callers will have the choice of alloc init pattern, or the factory
//
- (id)initWithName:(NSString *)name {
self = [self init];
if (self) {
_name = name;
}
return self;
}
然后調用者執行此操作:
ActivePlayer *activePlayer = [ActivePlayer activePlayerWithName:@"Charlie"];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.