2015-01-13 4 views
0

Я создал пользовательскую кнопку в ViewDidLoad, которая показывает новый вид (через downALevel):Пользовательская кнопка на панели навигации перестает работать

UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(downALevel:)]; 
self.navigationItem.rightBarButtonItem = addButton; 

В представлении нагрузок мелких и кнопка работает. Когда я вернусь к просмотру, кнопки будут отключены и не будут работать. Я использую Xcode 6; это не было проблемой в предыдущих версиях.

Любые идеи?

  • (IBAction) downALevel: (ID) отправитель {

    [самостоятельного showWaiting];

    [self performSelectorInBackground: (@ selector (callGrouper4)) сObject: nil];

}

- (Недействительными) showWaiting {

waitAlert = [[UIAlertView alloc] initWithTitle:@"Please Wait...." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil]; 


[waitAlert show];  

UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; 


indicator.center = CGPointMake(waitAlert.bounds.size.width/2, waitAlert.bounds.size.height - 50); 

[indicator startAnimating]; 
[waitAlert addSubview:indicator];  

}

- (Недействительными) callGrouper4 {// вниз уровень

@autoreleasepool { 

    float progressPercent; 
    NSString *progMsg; 
    NSString *curProgress; 
    NSNumberFormatter *formatter2 = [[NSNumberFormatter alloc] init]; 
    [formatter2 setNumberStyle: NSNumberFormatterDecimalStyle]; 
    [formatter2 setMinimumFractionDigits:0]; 
    [formatter2 setMaximumFractionDigits:0]; 

    NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init]; 
    NSPersistentStoreCoordinator *coordinator2 = [[self managedObjectContext] persistentStoreCoordinator]; 
    [newMoc setPersistentStoreCoordinator:coordinator2]; 
    [newMoc setUndoManager:nil]; 

    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    [request setEntity:[NSEntityDescription entityForName:@"TrialBalance" inManagedObjectContext:newMoc]]; 

.. .... много манипуляций с данными ......

// закончить

[waitAlert dismissWithClickedButtonIndex:0 animated:TRUE]; 

    reportBalances2 = nil; 



    Level2ActivityViewController *newController = [[Level2ActivityViewController alloc] initWithNibName:@"Level2ActivityViewController" bundle:[NSBundle mainBundle]]; 

    [newController setManagedObjectContext:newMoc]; 
    [newController setHeaderTitle:headerTitle]; 
    [newController setLevelToQuery:@"Obj2"]; 
    [newController setDdSumOrDetail:ddSumOrDetail]; 
    [newController setOrgNameVar:orgNameVar]; 
    [newController setPeriodNum:periodNum]; 
    [newController setReportMode:reportMode]; 
    [newController setSectionSort:@"obj1"]; 
    [[self navigationController] pushViewController:newController animated:YES]; 


} 

UPDATE 1 Давайте назовем первый вид А и новый вид B. Я только что обнаружил, что если B имеет тот же код, чтобы создать пользовательскую кнопку, а затем кнопку на A выключен. Если код отсутствует в B, тогда все будет хорошо. Я очень смущен ?? !!

+1

Не могли бы вы показать нам код 'downALevel:'? – wcd

+0

Вы что-то делаете, когда ваш контроллер просмотра исчезает, что может вызвать эту проблему? – user2955351

+0

downALevel - это почти 900 строк кода, которые управляют данными, которые затем представлены в новом представлении. Один и тот же код (downALevel) также можно выполнить с помощью жестов левого салфетки, который отлично работает, тогда как кнопка работает только один раз. Когда я вернусь к исходному виду, кнопка будет отключена, но жестом салфетки все равно будет работать. – Eusi

ответ

1

Кажется, что вы нарушаете пару обязанностей по теме здесь!

Прежде всего, вы вызываете performSelectorInBackground:, но внутри метода callGrouper4 вы не возвращаетесь к основному потоку, прежде чем нажимать контроллер вида. Имейте в виду, что UIKit не является потокобезопасным. Это может привести к странному поведению, как тот, который вы видите!

Также вы создаете NSManagedObjectContext без использования initWithConcurrencyType: api. Это означает, что ваш контекст управляемого объекта использует тип параллелизма NSConfinementConcurrencyType. Это означает, что вам не разрешено передавать этот контекст в другой поток, но вы назначаете его новому контроллеру представления, который, скорее всего, будет делать обращения к нему в основном потоке, который не является тем потоком, в котором он был создан.

При создании своего NSManagedObjectContext вы также устанавливаете координатор следующим образом: [[self managedObjectContext] persistentStoreCoordinator]. Я бы предположил, что контекст управляемого объекта, который вы запрашиваете здесь, был создан таким же образом, возможно, в другом потоке. В этом случае это тоже небезопасно!

В то время как проблема с двумя и тремя может привести к неожиданному поведению позже, проблема может быть легко вызвана тем, почему ваш пользовательский интерфейс ведет себя странно.

+0

Блестящий! Спасибо огромное! – Eusi

+0

Блестящий! Спасибо огромное! Я подумал, что как только код будет выполнен, он автоматически переключится на основной поток, но я следил за вашими советами по всем вопросам, внесенными изменениями, и все, кажется, работает отлично. Я новичок в кодировании iOS и действительно ценю время/усилия, в которых опытные кодеры, как и вы, помогают помогать таким людям, как я. Это моя цель, чтобы получить достаточно знаний, чтобы иметь возможность помогать другим :) – Eusi

+0

@Eusi, если вы новичок в iOS, вы можете захотеть выкопать в центральную диспетчерскую систему вместо того, чтобы использовать (старые) методы выбора. Это немного сложнее, но дает вам больше контроля, и из-за блочного api вы не теряете контекст с каждой очередью (что-то вроде потоков). –

Смежные вопросы