Background
My app takes data off a network stream, and changes values of UI elements on the screen. One element is a UITextView, which serves as a sort of log for the incoming data. It is supposed to update whenever the app receives a “HasBytesAvailable” NSStreamEvent with the nature of the data incoming. (eg if the data that comes in has to do with cake, the textview would update with something like “6/22/12 8:00 – got cake”) An example of how it updates is shown below.
[logString insertString:@"This is an update\n" atIndex:0];
//logstring is a MutableString I use to hold my UITextView's text
[logString insertString:timeString atIndex:0]; //timestring is current time
logView.text = logString; //logView is my UITextView
[logView flashScrollIndicators];
//logstring and logview declaration and implementation
@property (nonatomic,retain) IBOutlet UITextView *logView;
@property (nonatomic,retain) NSMutableString *logString;
logString = [[NSMutableString alloc] initWithString:@"-logging started\n"];
The Problem
The updating works as I want it as long as I don’t try to scroll the TextView. However, if I scroll through the text and hold it down, presumably long enough for my update code to be called, the app crashes when I stop scrolling. I can flick through the text just fine, it’s just when it has to handle an incoming packet and I’m still scrolling that it will crash. Furthermore, while I’m scrolling, nothing else will update. All the labels that are supposed to be updated by the data received stay the same.
My Thoughts
It’s as if the app can’t handle both scrolling and working with incoming data at the same time. I’m not sure if this is because I am doing something wrong with memory management, or I need to overwrite some scrolling function, or something else entirely. Any help or thoughts is appreciated.
Solution
As trumpetlicks said, I needed to implement multithreading for my network tasks
to do this I did the following:
in initialization:
NSOperationQueue *networkQueue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(initNetworkCommunication) object:nil];
[networkQueue addOperation:operation];
[operation release];
in initNetworkCommunication, after initializing CFSocketpair and streams:
[[NSRunLoop currentRunLoop] run]; //necessary to handle stream events
Start here.
developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… You may
also wish to add your networking setup and usage code so that we can all see what you are doing there!!!