#objective-c #memory-management #uiview #nsarray #yajl
#objective-c #управление памятью #uiview #nsarray #yajl
Вопрос:
Я пытаюсь извлекать данные JSON каждые 2 секунды и передавать их в другой класс для обработки, все работает нормально, но в приведенном ниже коде, похоже, есть утечки памяти (из инструментов), но я не могу понять, что не так и как я могу исправить, может кто-нибудь посоветовать, пожалуйста???
* Обновлено с полной логикой, и похоже, что массив, который передается в основной метод, протекает, и инструменты ошибочно сообщают об этом как об утечке YAJL..(ты не очень уверен)*
@property (nonatomic,retain,readwrite) NSMutableArray *deviceListArray;
- (void)viewDidLoad
{
[super viewDidLoad];
deviceListArray=[[NSMutableArray alloc]init];
[self init];
TestClass *initiateData = [GetData alloc]init];
[initiateData startTimer];
[initiateData release];
}
- (id) init{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receiveDeviceListNotification:)
name:@"devicelist"
object:nil];
}
- (void) receiveDeviceListNotification:(NSNotification *) notification{
deviceListArray=[notification object];
[deviceListTable reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [deviceListArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[deviceListArray retain]; //CRASHES WITHOUT RETAIN specified here
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.textColor = [UIColor redColor];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
[cell.textLabel setText:[deviceListArray objectAtIndex:indexPath.row]]; //CRASHES if i remove the retain on devicelistarray
return cell;
}
@class TestClass;
@implementation TestClass
- (void)startTimer:(NSString *)timerstring
{
if(timerstring ==@"StartNow")
{
NSLog(@"Timer started");
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(TestMethod:) userInfo:nil repeats:YES];
}
else{
NSLog(@"string not received");
}
}
-(void)TestMethod:(NSTimer *)Timer {
NSTimeInterval timeNow= [NSDate timeIntervalSinceReferenceDate];
NSData *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.example/data.json"]];
NSArray *testArray=[JSONData yajl_JSON]; //MEMORY LEAK HERE
if(testArray==nil)
{
NSLog(@"Array is nil");
}
else
{
NSArray *arrayNumberOne=[[testArray valueForKey:@"devicelist"]objectAtIndex:0];
NSArray *arrayNumberTwo=[testArray valueForKey:@"arrayNumberTwo"];
NSArray *arrayNumberThree=[testArray valueForKey:@"arrayNumberThree"];
float dowloadY=[[arrayNumberTwo objectAtIndex:0]floatValue];
float uploadY=[[arrayNumberThree objectAtIndex:0]floatValue];
NSDictionary *newarrayNumberTwoData= [NSDictionary dictionaryWithObjectsAndKeys:
[NSDecimalNumber numberWithInt:timeNow], [NSNumber numberWithInt:0],
[NSDecimalNumber numberWithFloat:dowloadY], [NSNumber numberWithInt:1],nil
] ;
NSDictionary *newarrayNumberThreeData= [NSDictionary dictionaryWithObjectsAndKeys:
[NSDecimalNumber numberWithInt:timeNow], [NSNumber numberWithInt:0],
[NSDecimalNumber numberWithFloat:uploadY], [NSNumber numberWithInt:1],nil
] ;
[[NSNotificationCenter defaultCenter] postNotificationName:@"devicelist" object:arrayNumberOne];
[[NSNotificationCenter defaultCenter] postNotificationName:@"TestData2" object:newarrayNumberTwoData];
[[NSNotificationCenter defaultCenter] postNotificationName:@"TestData3" object:newarrayNumberThreeData];
}
}
-(void) dealloc{
[super dealloc];
}
@end
Журнал утечек памяти из инструментов приведен ниже
Утечка объекта # Размер адреса, ответственный за библиотеку, ответственный за фрейм __NSArrayM,569 < несколько> 17,78 КБ MYTESTAPP3 -[YAJLDocument parserDidStartArray:] Malloc 80 байт,480 < кратных> 37,50 КБ MYTESTAPP3 -[YAJLDocument PARSER_DIDSTARTARRAY:] NSCFString,397 < кратных> 11,44 КБ Foundation -[nsplaceholderstr initWithBytes:длина:кодировка:] NSCFString, 0x4c1dac0 32 байта Foundation -[nsplaceholderstr initWithBytes:длина:кодировка:]
Комментарии:
1. Существует два yajl — один на C (который также имеет привязки к Haskell) и один на Ruby. Итак, я также пометил этот ruby.
2. Что такое Instaruments (или инструменты) — можете ли вы предоставить ссылку на него?
3. @Andrew Grimm я использую «Инструменты» из ссылки Xcode: developer.apple.com/technologies/tools
4. Как вы объявляете arrayNumberOne,arrayNumberTwo, arrayNumberThree?
5. @Nathan S локально, (sry, я пропустил это раньше). Я отредактировал вопрос с правильным объявлением
Ответ №1:
Ну, это выглядит просто. Сначала вы определили свои jsonData как ‘retain’ вместо ‘assign’, а затем при вызове метода тестирования в последующих запусках происходит утечка предыдущего, поскольку вы не используете установщик, а обращаетесь к переменной экземпляра напрямую. Если вам не нужны jsonData ни в каком другом месте, кроме этого метода, просто определите его как локальную переменную и не делайте ничего особенного — он автоматически освобождается. И второе — то же самое происходит с testArray. Опять же, если вам это не нужно в других местах, то определите как локальную переменную, и если вам это нужно, то используйте установщик.
Обновление: Теперь у вас аналогичная проблема, только на этот раз с deviceListArray. Сначала инициализируйте его следующим образом:
self.deviceListArray=[NSMutableArray array];
затем, каждый раз, когда вы хотите назначить, используйте это:
self.deviceListArray = newObject;
при освобождении выполните
[Выпуск deviceListArray];
Комментарии:
1. я внес поправки на основе ваших комментариев, но NSArray «testArray» все еще протекает в соответствии с инструментами
2. Теперь это больше похоже на ошибку YAJL. Если вы можете опубликовать код где-нибудь, я могу дать его посмотреть. Я посмотрел на github.com/gabriel/yajl-objc/blob/master/Classes/YAJLDocument.m , но не увидел ничего очевидного.
3. я обновил полную логику, и похоже, что devicearray, который передается в основной метод, вызывает утечку. если я удалю [devicelistarray retail] из-за (UITableViewCell *) метода TableView: (UITableView *) TableView cellForRowAtIndexPath: (NSIndexPath *)indexPath, он потерпел крах и сохранится, возможно, причиной утечки .. можете ли вы, пожалуйста, посоветовать, как исправить? tks