У меня возник странный вопрос, касающийся процесса, который, похоже, застревает в состоянии ожидания с случайными интервалами, и я надеюсь, что смогу получить некоторую помощь по этому поводу.
Когда пользователь запускаетВ приложении отображается окно, которое собирает различные данные и выбирает записи из списка файлов пользователя.Затем пользователь нажимает кнопку «Выполнить», и метод делегата приложения, связанный с кнопкой «Выполнить», создает экземпляр класса (TestBindingClass), в котором есть метод, который в конечном итоге будет выполняться в фоновом режиме.Затем он запускает второй файл XIB, который отображает второе окно, которое содержит пустой вид прокрутки.Как часть инициации второго окна в методе windowDIdLoad, код второго окна регистрируется как наблюдатель свойства TestBindingClass.Наконец, метод run в главном окне выполняет метод второго потока внутри TestBindingClass, который добавляет записи в NSMutableArray, а также запускает отслеживаемое свойство каждый раз, когда добавляется новая запись.Каждая запись в NSMutableArray представляет собой строку текста (строку), которая должна отображаться во втором виде прокрутки xib.
TestBindingClass - это (относительно) пустая оболочка класса, в которой будут содержаться обширные вычисления, которые будут генерировать сообщения о состоянии при достижении определенных контрольных точек.Эти сообщения контрольных точек будут отображаться в режиме прокрутки.
В основном, это работает нормально.На самом деле, иногда это работает отлично.В других случаях процесс, кажется, зависает и отображает только несколько строк состояния, прежде чем зависнуть в цикле ожидания.Обычно это точка, в которой вид прокрутки собирается расширяться за пределы размера окна, и полоса прокрутки активируется.Странно то, что если я добавляю точки отладки в метод add наблюдателя во втором коде XIB, он ВСЕГДА работает правильно.
Так много для описания ... давайте покажем некоторый код ....
Вот код для метода кнопки 'run' в главном окне
-(IBAction)runButtonPressed:(id)sender
{
// do a bunch of stuff
TestBindingClass* tempTestBindingClass = [[TestBindingClass alloc] init];
RunResultWindowController = [[RunResultWindow alloc] initWithWindowNibName:@"RunResultWindow"];
RunResultWindowController.localTestBindingClass=tempTestBindingClass;
[RunResultWindowController showWindow:self];
[self.StatusDisplayOutput setStringValue:@"Run Complete"];
[tempTestBindingClass submitStatusStringSequence];
}
Вот код для TestBindingClass, как указано выше.StatusStrings - это изменяемый массив, который будет содержать список строк состояния, которые должны в конечном итоге отображаться в представлении прокрутки, которое наблюдает за этим классом через свойство arraystatuscounter.
// TestBindingClass.h
#import <Foundation/Foundation.h>
@interface TestBindingClass : NSObject {
NSMutableArray *StatusStrings;
int arraystatuscounter;
}
@property (nonatomic, retain) NSMutableArray *StatusStrings;
@property int arraystatuscounter;
- (void) runStatusStringSequence:(id)param;
- (void) submitStatusStringSequence;
@end
Это показывает код TestBindingClass, который довольнопросто.Просто вставляйте по очереди глупые маленькие строки в NSMutableArray и каждый раз добавляйте свойство arraystatuscounter, добавляя строку в массив.
// TestBindingClass.m
- (void) submitStatusStringSequence
{
[NSThread detachNewThreadSelector:@selector(runStatusStringSequence:) toTarget:self withObject:nil];
}
- (void) runStatusStringSequence:(id)param
{
NSMutableArray *StatusStringsAlloc = [[NSMutableArray alloc] initWithCapacity:1];
StatusStrings = StatusStringsAlloc;
[StatusStrings addObject:[NSString stringWithString:@"first string"]];
[self setArraystatuscounter:1];
[StatusStrings addObject:[NSString stringWithString:@"second string"]];
[self setArraystatuscounter:2];
[StatusStrings addObject:[NSString stringWithString:@"third string"]];
[self setArraystatuscounter:3];
[StatusStrings addObject:[NSString stringWithString:@"fourth string"]];
[self setArraystatuscounter:4];
[StatusStrings addObject:[NSString stringWithString:@"fifth string"]];
[self setArraystatuscounter:5];
[StatusStrings addObject:[NSString stringWithString:@"sixth string"]];
[self setArraystatuscounter:6];
[StatusStrings addObject:[NSString stringWithString:@"seventh string"]];
[self setArraystatuscounter:7];
[StatusStrings addObject:[NSString stringWithString:@"last string"]];
[self setArraystatuscounter:8];
[StatusStrings addObject:[NSString stringWithString:@"first string"]];
[self setArraystatuscounter:1];
[StatusStrings addObject:[NSString stringWithString:@"second string"]];
[self setArraystatuscounter:2];
[StatusStrings addObject:[NSString stringWithString:@"third string"]];
[self setArraystatuscounter:3];
[StatusStrings addObject:[NSString stringWithString:@"fourth string"]];
[self setArraystatuscounter:4];
[StatusStrings addObject:[NSString stringWithString:@"fifth string"]];
[self setArraystatuscounter:5];
[StatusStrings addObject:[NSString stringWithString:@"sixth string"]];
[self setArraystatuscounter:6];
[StatusStrings addObject:[NSString stringWithString:@"seventh string"]];
[self setArraystatuscounter:7];
[StatusStrings addObject:[NSString stringWithString:@"last string"]];
[self setArraystatuscounter:8];
}
Вот код контроллера окна RunResultWindows.Адрес для TestBindingClass добавляется в ivars, чтобы он мог правильно настроить необходимые параметры наблюдателя KVO.
// RunResultWindow.h
@interface RunResultWindow : NSWindowController {
NSTextView *RunResultWindowTextView;
TestBindingClass *localTestBindingClass;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
@property (strong) IBOutlet NSTextView *RunResultWindowTextView;
@property (nonatomic, retain) TestBindingClass *localTestBindingClass;
@end
Вот интересующие нас методы RunResultWindow.Прошу прощения за массив, если оператор, который был добавлен туда для некоторых временных целей отладки и никогда не удалялся.
// RunResultWindow.m methods of interest
- (void)windowDidLoad
{
[super windowDidLoad];
NSWindow *wcWindow;
wcWindow = [self window];
[wcWindow makeKeyAndOrderFront:self];
NSString *teststring;
teststring = [NSString stringWithString: @"show first time window did load "];
[RunResultWindowTextView setString:teststring];
[RunResultWindowTextView display];
[localTestBindingClass addObserver:self
forKeyPath:@"arraystatuscounter"
options:NSKeyValueObservingOptionNew
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change
context:(void *)context
{
NSInteger arrayCount;
NSString* localDisplayString;
NSString* localNewlinePlusDisplayString;
NSTextStorage *tempTextStorage;
tempTextStorage = [RunResultWindowTextView textStorage];
arrayCount = [ localTestBindingClass.StatusStrings count ];
if (arrayCount >= 1) {
arrayCount--;
localDisplayString = [localTestBindingClass.StatusStrings objectAtIndex:arrayCount];
localNewlinePlusDisplayString = [@"\n" stringByAppendingString:localDisplayString];
[tempTextStorage beginEditing];
[tempTextStorage replaceCharactersInRange:NSMakeRange([tempTextStorage length] - 1, 0)
withString:localNewlinePlusDisplayString];
[tempTextStorage endEditing];
[RunResultWindowTextView display];
}
}