Activity Indicator

Discussion in 'iOS Programming' started by Dman90, Apr 9, 2012.

  1. Dman90 macrumors newbie

    Joined:
    Jun 25, 2011
    #1
    Hi Guys,

    I have an activity indicator in my application in a number of places and I am having the same problem everywhere.

    In the login page, when the user enters their details, and presses the login button, a method is called that checks if the details are right or not. While this method is being called an activity indicator is meant to show on the screen.

    My problem is that the indicator shows at the end, just before the new view is loaded, rather then when the login credentials are being checked.

    How can I activate it as soon as the button is pressed.

    This is the method that is called when the login button is pressed:
    Code:
    {
         self.spinner.hidden = NO;
                                        
        [spinner startAnimating];
    
        URL connection to the database
    
        if statement check the reply for the database
    
       if credentials are correct new page is loaded.
    }
    
    
    As you can see from the method, I activate the spinner as soon as the method is called.

    Any help would be greatly appreciated.

    Thanks.
     
  2. Sykte macrumors regular

    Joined:
    Aug 26, 2010
    #2

    I'm going to take a shot in the dark and say you're hanging the main thread in the code (bold).

    Edit: You can quickly check this out if you comment out the code above. Also if your url connection to the database isn't on a separate thread it should be.
     
  3. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #3
    Oddly enough I had this happen last week working on my app. I fixed it by using the NSThread which allows you to break off the selected method and run it on the background. This allowed the indicator to spin until the process was finished.

    The trick for me was to start it spinning [spinner startAnimating]; the the next line was the NSThread to process something like someMethod. Then at the end of someMethod just before it returned I used the code [spinner stopAnimation];

    It was this code basicly
    Code:
         }
        }
        [activityIndicator startAnimating];
        
        [NSThread detachNewThreadSelector:@selector(backgroundThreadLoad) toTarget:self withObject:nil];
    
    
    -(void)backgroundThreadLoad{
            @autoreleasepool {
    process this data....
            }
    [activityIndicator stopAnimating];
    }
    
    
     
  4. Dman90 thread starter macrumors newbie

    Joined:
    Jun 25, 2011
    #4
    I tried to do that for my code but I got the following error.

    2012-04-10 00:40:49.811 In4merz[2939:380b] void _WebThreadLockFromAnyThread(bool), 0x21f1d0: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread.
    2012-04-10 00:40:52.920 In4merz[2939:380b] bool _WebTryThreadLock(bool), 0x21f1d0: 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...
    1 _ZL17_WebTryThreadLockb
    2 WebThreadLock
    3 -[UITextRangeImpl isEmpty]
    4 -[UITextRange(UITextSelectionAdditions) _isCaret]
    5 -[UITextSelectionView setCaretBlinks:]
    6 -[UIKeyboardImpl setCaretBlinks:]
    7 -[UIKeyboardImpl setDelegate:force:]
    8 -[UIPeripheralHost(UIKitInternal) _reloadInputViewsForResponder:]
    9 -[UINavigationController navigationTransitionView:didStartTransition:]
    10 -[UINavigationTransitionView transition:fromView:toView:]
    11 -[UINavigationTransitionView transition:toView:]
    12 -[UINavigationController _startTransition:fromViewController:toViewController:]
    13 -[UINavigationController _startDeferredTransitionIfNeeded]
    14 -[UINavigationController pushViewController:transition:forceImmediate:]
    15 -[UINavigationController pushViewController:animated:]
    16 -[login validateLogin:]
    17 -[login backgroundThreadLoad]
    18 -[NSThread main]
    19 __NSThread__main__
    20 _pthread_start
    21 thread_start
    (lldb)



     
  5. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #5
    I'd recommend using NSURLConnection instead of NSThread for this kind of work.
     
  6. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #6
    From within my backGroundThreadLoad Method I do have a few [self someMethods]; that execute. One of them first tests to see if the file it is looking for even exists before continuing. I use this Method to test to see if the file exists first before I do anything. It uses the NSURLConnection that Dejo (whom has helped me countless times understand all of this as I also learn). I wrap it up in a if statement

    if ([self webFileExists: @"www.site/dir/blah.txt]") {
    do this....
    }
    else{
    do this....
    }



    Code:
    -(BOOL) webFileExists:(NSString *) address {
        
        NSString *url = address;
        
        NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString: url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];
        NSHTTPURLResponse* response = nil;
        NSError* error = nil;
        [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
        
        if ([response statusCode] == 404)
            return NO;
        else
            return YES;
    }
    
    
    Please take all of this with a grain of salt. I just started to learn about NSThreads a month ago.
     
  7. Sykte macrumors regular

    Joined:
    Aug 26, 2010
    #7

    I would either use [NSURLConnection sendAsynchronousRequest:queue:completionHandler:]; In the completionHandler stop your animation then push the new controller.

    or

    Wrap your everything inside of two blocks. The first block would use a background thread to call network stuff, then a second block on the main thread to update UI objects, think UIKIT.

    Code:
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.appName.taskNameHere",NULL);
    dispatch_async(backgroundQueue, ^{
        //do networking stuff here
       //do networking stuff here
    
    dispatch_async(dispatch_get_main_queue(), ^{
            //stop animation
           //update other UI related stuff
           //even push your view controller if needed.
        });
    
    });
    
     
  8. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    I'm also curious why you feel the need to reference spinner using self in one line and then without in the very next.
     

Share This Page