How to read SQLite data in child thread

Discussion in 'iOS Programming' started by Narendar Singh, Oct 3, 2012.

  1. Narendar Singh macrumors member

    Narendar Singh

    Joined:
    Jun 22, 2012
    Location:
    INDIA
    #1
    I have few hundredths of rows in my few tables. If I read these rows from main thread UI goes unresponsive.

    I want to read these rows in some other thread so that my UI thread wont get stuck
    (seems in iOS it is related to dispatch queue kind of thing, dont know very much)

    I have written few code based on my understanding but my application is getting crash.

    // This is my .h file

    Code:
    @interface HistoryViewController : UIViewController
    {
        NSArray *data1; 
        NSArray *data2;
        NSArray *data3;
    }
    
    @property (nonatomic, retain) NSArray *data1; 
    @property (nonatomic, retain) NSArray *data2;
    @property (nonatomic, retain) NSArray *data3;
    Code:
    // This is my .m file
    
    @synthesize data1, data2, data3;
    
    - (void)readLocalDBData
    {
        // start the activity indicator
        [self.view addSubview:fadeView];
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            DebugLog(@"STARTED LONG RUNNING TASK FROM HERE... "); 
    
            _data1  = [GetAppDelegate().databaseWrapper getDataFromTable1]; // returns nil in case of zero rows
            _data2  = [GetAppDelegate().databaseWrapper getDataFromTable2]; // returns nil in case of zero rows
            _data3  = [GetAppDelegate().databaseWrapper getDataFromTable3]; // returns nil in case of zero rows
    
            dispatch_async(dispatch_get_main_queue(), ^{
               
                 DebugLog(@"FINISHED MY LONG RUNNING TASK...");
               
                // stop activity indicator
                [self.fadeView removeFromSuperview];
    
                // update ui method called
                [self updateUI];
            });
        });
    }    
    
    - (void)updateUI
    {
        
        if (data1 == nil) 
        {
            [self.fadeView removeFromSuperview];
            return;
        }
    
    [COLOR="Red"][B]   // in this line I am getting crash with EXE_BAD_ACCESS    
        DebugLog(@"History Items %@", [data1 count]);[/B][/COLOR]
    
        DebugLog(@"NEWS History Items %d",  [data2 count]);
    
        DebugLog(@"PRODUCT History Items %d", [data3 count]);
    
    }
     
  2. jnoxx macrumors 65816

    jnoxx

    Joined:
    Dec 29, 2010
    Location:
    Aartselaar // Antwerp // Belgium
    #2
    First of all, no need to create local ivar's AND property's
    you can @synthesize data1 = _data1; and this will also create an ivar object for you.. :)
    I don't understand why you make a difference between self.object and _object & object, you don't really know what to call when do you? (no offense, just asking).
    And you say you get an error on an Bad EXCESS, which generally means you have an memory issue, are you using ARC or not?

    Also, getting your data from the APpDelegate is really bad, and why do you use the ()? it's not really Java or C# or whatever here :p
    And also in the updateUI, is your actual data1 setted or not?
     
  3. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #3
    If you access a sqlite db from more than one thread you need to get a database handle in each thread. Do not use the same database handle from more than one thread.

    Don't access ivars directly (like _data = blah). Only use the @property. (like self.data = blah blah).

    Don't access the UI from a background thread.

    You should probably not use GCD. It is a low-level C API and a little complicated. Use NSOperation.
     
  4. Narendar Singh, Oct 4, 2012
    Last edited by a moderator: Oct 4, 2012

    Narendar Singh thread starter macrumors member

    Narendar Singh

    Joined:
    Jun 22, 2012
    Location:
    INDIA
    #4
    Mistake from my side,
    Code:
    _data1  = [GetAppDelegate().databaseWrapper getDataFromTable1]; // returns nil in case of zero rows
    _data2  = [GetAppDelegate().databaseWrapper getDataFromTable2]; // returns nil in case of zero rows
    _data3  = [GetAppDelegate().databaseWrapper getDataFromTable3]; // returns nil in case of zero rows
    
    it was actually
    Code:
    data1  = [GetAppDelegate().databaseWrapper getDataFromTable1]; // returns nil in case of zero rows
    data2  = [GetAppDelegate().databaseWrapper getDataFromTable2]; // returns nil in case of zero rows
    data3  = [GetAppDelegate().databaseWrapper getDataFromTable3]; // returns nil in case of zero rows
    
    No, how to use that?

    I have a helper class in which I have created C style function which return application delegate object. Do you feel it is wrong way? Please confirm.
    Code:
    AppDelegate* GetAppDelegate()
    {
    	return (AppDelegate*)[[UIApplication sharedApplication] delegate];
    }
    It may nil or some values based on this following call:
    Code:
    data1  = [GetAppDelegate().databaseWrapper getDataFromTable1]; // returns nil in case of zero rows
    
     

Share This Page