0

I want to manipulate views while in a for loop. I manipulate a view in the for loop, then the operations for the view are done at once after the for loop has ended. I tried to use other threads like GCD, but I noticed that a view is in the main thread. The operations are back to the main thread and they are put off after the for loop finishes.

What I want to do is update UITextView's text while in the for loop. If I can't operate the for loop in another thread, how can I do that? Are there other ways to do that?

rekire
  • 47,260
  • 30
  • 167
  • 264
morizotter
  • 1,926
  • 2
  • 24
  • 34

1 Answers1

1

Solution 1: Use a timer

In order to progressively add text to a textview, you can use an NSTimer.

Requirements

in your interface - the following ivars or properties:

UITextView *textView;

NSNumber *currentIndex;

NSTimer *timer;

NSString *stringForTextView;

Assuming the string is created and the textview is set up, you can create a function to create the timer and kick it off:

- (void) updateTextViewButtonPressed
{


   timer = [NSTimer scheduledTimerWithTimeInterval:.5
                                     target:self
                                   selector:@selector(addTextToTextView)
                                   userInfo:nil
                                    repeats:YES];


}

- (void) addTextToTextView
{
    textView.text = [string substringToIndex:currentIndex.integerValue];
    currentIndex = [NSNumber numberWithInt:currentIndex.integerValue + 1];

    if(currentIndex.integerValue == string.length)
    {
        [_timer invalidate];
        timer = nil;
    }
}

This is a basic working implementation, and you can vary it to pass in the string as userInfo for the timer, if it is not present at the class level. Then you could access it in your addTextToTextView selector with sender.userInfo. You can also adjust the timer interval and how exactly the text is added. I used half a second and character by character concatenation as an example.


Solution 2: Use a loop

Requirements

NSString *string

UITextview *textView

- (void) updateTextViewButtonPressed
{
    // perform the actual loop on a background thread, so UI isn't blocked
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^()
                   {
                       for (int i = 0; i < string.length; i++)
                       {
                           // use main thread to update view
                           dispatch_async(dispatch_get_main_queue(), ^()
                                          {
                                              textView.text = [string substringToIndex:i];

                                          });

                           // delay
                           [NSThread sleepForTimeInterval:.5];
                       }
                   });


}
Dima
  • 23,484
  • 6
  • 56
  • 83
  • Your code done well. I tried that. But I want to use for-loop in the main thread. Is it impossible? – morizotter Sep 13 '12 at 17:56
  • The problem isn't that it's not performing on the main thread, it's that it is happening too fast. updating my answer with a solution using NSTimer. – Dima Sep 13 '12 at 19:48
  • Thank you. I tried your solution. It worked well. But it also works after for loop ended. If for-loop takes time, the view didn't change for long time. – morizotter Sep 14 '12 at 03:08
  • using the second method, you should get rid of the for loop altogether. the timer will kick off every n seconds and does not require a loop to run. – Dima Sep 14 '12 at 06:49
  • I don't want to use timers but for-loop. Your code works well and one of the alternatives but doesn't solve my question. But thank you wrote code! – morizotter Sep 16 '12 at 06:13
  • I'll do add another alternative, using a loop (if you really need one). – Dima Sep 16 '12 at 23:04