Объектив-C блокировка не выпущена для приложений только для фона

StackOverflow https://stackoverflow.com/questions/3565600

Вопрос

У меня есть приложение, которое работает только на заднем плане (указав LSBackgroundOnly в файле info.plist). Проблема в том, что все блоки, которые я работаю на параллельных очередях, не выпускаются. Код выполнен в управляемой памяти среде - нет GC.

(Упрощенный) код выглядит ниже. Blubber - это просто какой-то макетный класс, который содержит NSDate для тестирования. Кроме того, он перезаписывает retain, release, а также dealloc Чтобы сделать какую-то ведение журнала:

NSOperationQueue *concurrentQueue = [[NSOperationQueue alloc] init];
[concurrentQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];

Blubber *aBlubber = [[Blubber alloc] init]; 
aBlubber.aDate = [NSDate date];

[concurrentQueue addOperationWithBlock:^{       
NSAutoreleasePool *blockPool = [[NSAutoreleasePool alloc] init];
    NSDate *test = [aBlubber aDate];
    NSLog(@"Block DONE");
    [blockPool release];    
}];

[aBlubber release];

[concurrentQueue release];

Если я изменил приложение, чтобы быть нормальным (т. Е. Незаписывающим) приложением, я могу наблюдать, что блоки, выделяемые всякий раз, когда любой вход выполнен через UI (даже изменение фокусировки на другое окно достаточно). Поскольку мое приложение BackgoRund получает вход непосредственно над драйвером USB HID, и у него нет окна или строки меню, это не происходит.

Есть ли способ вручную заставить unloop или что-то, что отвечает за то, чтобы сообщить очередям освободить готовые блоки?

(Все остальные объекты, которые были сохранены блоками, также не выпущены, создавая огромные утечки памяти. Эти утечки не могут быть подлежащеными к утечками или инструментами Objects Allocations, но потребление памяти можно наблюдать за помощью

Это было полезно?

Решение

Один общий «gotcha» для авторелезных пулов состоит в том, что если приложение создает память без получения событий, внешний вид Бассейн (тот управляемый петлей событий) не будет сливаться.

Я не думаю, что это должно подать заявку здесь, так как вы управляете своим собственным бассейном ... Но на всякий случай, вы можете попробовать это:

...
//When no events are coming in (i.e. the user is away from their computer), the runloop doesn't iterate, and we accumulate autoreleased objects
[[NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:@selector(kickRunLoop:) userInfo:nil repeats:YES] retain];
...
- (void) kickRunLoop:(NSTimer *)dummy
{
// Send a fake event to wake the loop up.
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
                                    location:NSMakePoint(0,0)
                               modifierFlags:0
                                   timestamp:0
                                windowNumber:0
                                     context:NULL
                                     subtype:0
                                       data1:0
                                       data2:0]
         atStart:NO];
}

Другие советы

Похоже, вы используете блок на базе стека, который используется после того, как блок исчезла из объема. Блок должен быть скопирован. Код должен работать, если он изменен на это:

[concurrentQueue addOperationWithBlock:[[^{       
    NSAutoreleasePool *blockPool = [[NSAutoreleasePool alloc] init];
    NSDate *test = [aBlubber aDate];
    NSLog(@"Block DONE");
    [blockPool release];    
}copy]autorelease]];

Посмотрите на этот пост для полной записи на блоках: http://gkoremanman.com/blog/2011/02/27/blocks-in-c-and-objective-c/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top