遇到这么一个泄漏事件:
环境:Xcode 4.2.1,mac 10.7.1
先看代码:
.h
View Code
1 @interface TableController : UITableViewController 2 3 @property (nonatomic ,retain) NSArray *DataSource; 4 5 @end
.m
1 #import "TableController.h" 2 #import "TableView.h" 3 #import "CellItem.h" 4 #import "Et.h" 5 6 #import "DetailController.h" 7 8 @implementation TableController 9 10 @synthesize DataSource = _DataSource; 11 12 - (void)defaultValues 13 { 14 self->_DataSource = nil; 15 } 16 17 - (void)loadDatasFromDB 18 { 19 if (self->_DataSource) 20 [self->_DataSource release]; 21 self->_DataSource = nil; 22 23 // load data from db 24 // test code b 25 NSMutableArray *mutDatas = [[NSMutableArray alloc] init]; 26 27 for (int i=0; i<10; i++) 28 { 29 Et *item = [[Et alloc] init]; 30 item.ID = i; 31 item.RecordDate = [NSDate date]; 32 item.Content = [NSString stringWithFormat:@"%d,%@",i ,item.RecordDate]; 33 34 [mutDatas addObject:item]; 35 36 [item release]; 37 } 38 39 self->_DataSource = [[NSArray alloc] initWithArray:mutDatas]; 40 [mutDatas removeAllObjects]; 41 [mutDatas release]; 42 mutDatas = nil; 43 // test code e 44 } 45 46 - (void)gotoView:(id)sender 47 { 48 DetailController *detailViewController = [[DetailController alloc] init]; 49 [self.navigationController pushViewController:detailViewController animated:YES]; 50 [detailViewController release]; 51 } 52 53 - (void)navSetting 54 { 55 self.navigationItem.title = @"Title"; 56 57 UIBarButtonItem *btnSettings 58 = [[UIBarButtonItem alloc] initWithTitle:@"+" 59 style:UIBarButtonItemStyleBordered 60 target:self 61 action:@selector(gotoView:)]; 62 self.navigationItem.rightBarButtonItem = btnSettings; 63 [btnSettings release]; 64 } 65 66 - (id)init 67 { 68 self = [super init]; 69 if (self) 70 { 71 [self defaultValues]; 72 [self loadDatasFromDB];/// ------注意:LeakProblem 73 } 74 75 return self; 76 } 77 78 - (id)initWithStyle:(UITableViewStyle)style 79 { 80 self = [super initWithStyle:style]; 81 if (self) { 82 // Custom initialization 83 [self defaultValues]; 84 [self loadDatasFromDB];/// ------注意:LeakProblem 85 } 86 return self; 87 } 88 89 - (void)dealloc 90 { 91 if (self.DataSource) 92 [self->_DataSource release]; 93 94 [self defaultValues]; 95 96 [super dealloc]; 97 } 98 99 - (void)didReceiveMemoryWarning 100 { 101 // Releases the view if it doesn't have a superview. 102 [super didReceiveMemoryWarning]; 103 104 // Release any cached data, images, etc that aren't in use. 105 } 106 107 #pragma mark - View lifecycle 108 109 - (void)loadView 110 { 111 TableView *v = [[TableView alloc] init]; 112 v.dataSource = self; 113 v.delegate = self; 114 self.view = v; 115 [v release]; 116 } 117 118 - (void)viewDidLoad 119 { 120 [super viewDidLoad]; 121 122 // Uncomment the following line to preserve selection between presentations. 123 // self.clearsSelectionOnViewWillAppear = NO; 124 125 // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 126 // self.navigationItem.rightBarButtonItem = self.editButtonItem; 127 [self navSetting]; 128 129 [self loadDatasFromDB];/// ------注意:LeakProblem 修复方式 130 } 131 132 - (void)viewDidUnload 133 { 134 [super viewDidUnload]; 135 // Release any retained subviews of the main view. 136 // e.g. self.myOutlet = nil; 137 138 if (self->_DataSource) 139 [self->_DataSource release]; 140 self->_DataSource = nil; 141 } 142 143 - (void)viewWillAppear:(BOOL)animated 144 { 145 [super viewWillAppear:animated]; 146 } 147 148 - (void)viewDidAppear:(BOOL)animated 149 { 150 [super viewDidAppear:animated]; 151 } 152 153 - (void)viewWillDisappear:(BOOL)animated 154 { 155 [super viewWillDisappear:animated]; 156 } 157 158 - (void)viewDidDisappear:(BOOL)animated 159 { 160 [super viewDidDisappear:animated]; 161 } 162 163 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 164 { 165 // Return YES for supported orientations 166 return (interfaceOrientation == UIInterfaceOrientationPortrait); 167 } 168 169 #pragma mark - Table view data source 170 171 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 172 { 173 //#warning Potentially incomplete method implementation. 174 // Return the number of sections. 175 if (self.DataSource) 176 return 1; 177 return 0; 178 } 179 180 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 181 { 182 //#warning Incomplete method implementation. 183 // Return the number of rows in the section. 184 if (self.DataSource) 185 return self.DataSource.count; 186 return 0; 187 } 188 189 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 190 { 191 static NSString *CellIdentifier = @"Cell"; 192 193 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 194 if (cell == nil) 195 { 196 cell = [[[CellItem alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 197 198 if (self.DataSource) 199 { 200 if (self.DataSource.count > indexPath.row) 201 { 202 id cellData = [self.DataSource objectAtIndex:indexPath.row]; 203 204 if ([cellData isKindOfClass:[Et class]]) 205 { 206 Et *etItem = (Et *)cellData; 207 208 CellItem *c = (CellItem *)cell; 209 210 if (etItem.RecordDate) 211 { 212 NSRange range; 213 range.location = 0; 214 range.length = 10; 215 [c.LblRecordDate setText:[[NSString stringWithFormat:@"%@" ,etItem.RecordDate] substringWithRange:range]]; 216 } 217 218 if (etItem.Content) 219 { 220 NSRange range; 221 range.location = 0; 222 if (etItem.Content.length >10) 223 range.length = 10; 224 else 225 range.length = etItem.Content.length; 226 [c.LblSimpleContent setText:[etItem.Content substringWithRange:range]]; 227 } 228 229 if (c.LblRecordDate) 230 [c addSubview:c.LblRecordDate]; 231 232 if (c.LblSimpleContent) 233 [c addSubview:c.LblSimpleContent]; 234 } 235 236 } 237 } 238 } 239 240 return cell; 241 } 242 243 /* 244 // Override to support conditional editing of the table view. 245 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 246 { 247 // Return NO if you do not want the specified item to be editable. 248 return YES; 249 } 250 */ 251 252 /* 253 // Override to support editing the table view. 254 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 255 { 256 if (editingStyle == UITableViewCellEditingStyleDelete) { 257 // Delete the row from the data source 258 [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 259 } 260 else if (editingStyle == UITableViewCellEditingStyleInsert) { 261 // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 262 } 263 } 264 */ 265 266 /* 267 // Override to support rearranging the table view. 268 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath 269 { 270 } 271 */ 272 273 /* 274 // Override to support conditional rearranging of the table view. 275 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath 276 { 277 // Return NO if you do not want the item to be re-orderable. 278 return YES; 279 } 280 */ 281 282 #pragma mark - Table view delegate 283 284 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 285 { 286 // Navigation logic may go here. Create and push another view controller. 287 /* 288 <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil]; 289 // ... 290 // Pass the selected object to the new view controller. 291 [self.navigationController pushViewController:detailViewController animated:YES]; 292 [detailViewController release]; 293 */ 294 295 NSLog(@"%d" ,indexPath.row); 296 } 297 298 @end
代码中/// ------注意:LeakProblem和/// ------注意:LeakProblem 修复方式 两处语句互斥,不同时存在
保留/// ------注意:LeakProblem,删除/// ------注意:LeakProblem 修复方式
使用Analyze工具分析,没有泄漏代码
使用Profile工具分析,会出现loadDatasFromDB中一个NSArray数组以及10个内容泄漏
在调试中,尝试关闭loadDatasFromDB,在applicationDelegate.m中定义一个数组,赋予给属性Datasource,分别用上述工具再次分析,发现无泄漏
思考再三,移出在init中对loadDatasFromDB函数的调用,在viewDidLoad中调用
就是:
删除/// ------注意:LeakProblem,保留/// ------注意:LeakProblem 修复方式
又用上述工具分析,无泄漏
至于为什么第一种方式会导致profile泄漏,暂时没有找到合适说法
晚点再用xcode4.3.2试下【尝试了,和上述结论一样】
2012-06-28