views:

108

answers:

1

I am writing a program that displays to a console-like UITextView different events generated by my AudioSession and AudioQueues. For instance, when I detect that my audio route has changed, I just want a quickie message displayed on the screen on my iPhone that this happened. Unfortunately, I believe I am getting into some race condition nastiness, and I'm not sure what the best solution to solve this is.

When I run my program, my debug console spits this out:

bool _WebTryThreadLock(bool), 0x1349a0: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...

This happens on a line of code:

textView.text = string;

I tried this:

[textView performSelectorOnMainThread:@selector(setText:) withObject:string waitForDone:YES];

And this seemed to have fixed it, but I'm pretty sure I shouldn't be doing something like this to get it to work. Unfortunately, this doesn't work with [UITextView scrollVisibleWithRange:] since this takes an NSRange, which isn't a descendant of NSObject. I think what I am doing is fundamentally wrong.

This code is called from an interruption listener, which runs from the audio queue's thread. Is there something that I should be doing that will make my updates to my textview blocking so I'm not getting this problem?

Thanks.

+1  A: 
  1. You are allowed to do anything about the view only from main thread, you did the right thing.
  2. If it requires more parameters or primitive you may need a proxy function.

This is how I make a proxy function

// the caller should be like this
UTMainThreadOperationTextViewScroll *opr = [[UTMainThreadOperationTextViewScroll alloc] init];
opr.textView = textView;
opr.range = NSMakeRange(5, 10);
[UTMainThread performOperationInMainThread:opr];
[opr release];

// the Utility classes goes below
@interface UTMainThreadOperation : NSObject
- (void)executeOperation;
@end

@implementation UTMainThread

+ (void)performOperationInMainThread:(UTMainThreadOperation *)operaion
{
    [operaion performSelectorOnMainThread:@selector(executeOperation) withObject:nil waitUntilDone:NO];
}

@end

@implementation UTMainThreadOperationTextViewScroll

@synthesize textView;
@synthesize range;

- (void)dealloc { /* I'm too lazy to post it here */ }

- (void)executeOperation
{
    [textView scrollVisibleWithRange:range];
}

@end

PS. some declarations omitted

iwat