Discussion Forums  >  Plugins, Customizing, Source Code

Replies: 3    Views: 67

AlanMac
Aspiring developer
Profile
Posts: 2435
Reg: Mar 05, 2012
Esher, UK
35,350
01/08/17 10:14 AM (1 week ago)

App refresh?

Is anyone else having problems with BT 4 App refresh or is it just me?

I built an ios test app, but if I make changes in the control panel, they don't ripple out to the app. I've tried most of the obvious things, I've even tried just waiting!. The only way it works for me is if I remove the app from phone memory and re-load it.
 
ehwright
Aspiring developer
Profile
Posts: 53
Reg: Feb 21, 2012
Perth
2,330
like
01/09/17 01:44 AM (1 week ago)
Hi Allan,

I have been able to get mine to refresh. I'll give you the code changes I made so you can try it yourself. Please copy your project first just in case it goes pear shaped!

**** In the BT_database.m file,
line 1415
change: if(itemRows.count ==1){
to this: for (int i=0; i< itemRows.count; i++){

add this method to the bottom of the file -

//ehw jan 2017 sort out the tabs for the application, they may be old ones we dont want any more....
-(void)getTabsForApplication:(NSString *)tableName withRows:(NSArray *)rows{
[BT_debugger showIt:self message:[NSString stringWithFormat:@"sorting application tabs from update: \"%@\"", tableName]];

/*

DO NOT CALL THIS METHOD TO INSERT ONE RECORD. USE THE
insertRowIntoTable METHOD INSTEAD.

To use this method, and insert many like-records, provide an NSArray of NSDictionary
objects. Like-records means all the rows inserted have the same column names in the
same order. Naturally each row will contain different values...

NSMutableDictionary *row1Data = [[NSMutableDictionary alloc] init];
[row1Data setObject:@"A UNIQUE ID" forKey:@"guid"];
[row1Data setObject:@"David" forKey:@"firstName"];
[row1Data setObject:@"Book" forKey:@"lastName"];

NSMutableDictionary *row2Data = [[NSMutableDictionary alloc] init];
[row2Data setObject:@"A UNIQUE ID" forKey:@"guid"];
[row2Data setObject:@"Bill" forKey:@"firstName"];
[row2Data setObject:@"Jones" forKey:@"lastName"];

*/

//must have rows...
if([rows count] < 1){
[BT_debugger showIt:self message:[NSString stringWithFormat:@"tabsForTable ERROR: %@", @"zero rows provided"]];
return;
}
// first we delete the tabs for the application that in in the database, then insert the tab records so they are the only ones that exist.
NSMutableArray *tabs = [appDelegate.rootApp getTabs];

//loop through each tab bar item in application data
for(int i = 0; i < [tabs count]; i++){

//this tab
BT_item *thisTab = (BT_item *)[tabs objectAtIndex:i];
// remove this tab from the database

[self deleteRowFromTable:tableName withGuid:thisTab.itemId];
NSLog(@"deleting from table with guid: %@", thisTab.itemId);


}

// after deleting all the tabs, we then add the new ones back in...

//analyze the first row in the provided array to determine the column types for the insert...
NSDictionary *firstRow = [rows objectAtIndex:0];

//build an list of column data types to be used in the sql statement....
NSArray *tableColData = [self getColumnInfoForTable:tableName];
NSMutableDictionary *colDataTypes = [[NSMutableDictionary alloc] init];
NSArray *allKeys = [firstRow allKeys];
for(int i = 0; i < allKeys.count; i++){

//get column information for this field...
for(NSMutableDictionary *colInfo in tableColData){
if([colInfo objectForKey:@"colName"] != nil && [colInfo objectForKey:@"colType"] != nil){
if([[colInfo objectForKey:@"colName"] isEqualToString:[allKeys objectAtIndex:i]]){
[colDataTypes setObject:[colInfo objectForKey:@"colType"] forKey:[allKeys objectAtIndex:i]];
break;
}
}
}
}

//open database...
[self openDatabase];

//insert each row, wrap in sqlite transaction to speed things up...
char* errorMessage;
sqlite3_exec(sqlite3Database, "BEGIN TRANSACTION", NULL, NULL, &errorMessage);
sqlite3_stmt *statement;

NSString * sql = [NSString stringWithFormat:@"INSERT INTO %@ (", tableName];
for(int i = 0; i < allKeys.count; i++){
sql = [sql stringByAppendingString:[NSString stringWithFormat:@"%@, ", [allKeys objectAtIndex:i]]];
}
sql = [sql substringToIndex:[sql length] - 2];
sql = [sql stringByAppendingString:@") values ("];
for (int i = 0; i < allKeys.count; i++) {
sql = [sql stringByAppendingString:@"?, "];
}
sql = [sql substringToIndex:[sql length] - 2];
sql = [sql stringByAppendingString:@")"];
const char *query = [sql UTF8String];

if(sqlite3_prepare_v2(sqlite3Database, query, -1, &statement, nil) == SQLITE_OK){

//bind each row...
for(NSDictionary *row in rows){

//bind each column...
for(int i = 0; i < allKeys.count; i++){

NSString *colType = [colDataTypes objectForKey:[allKeys objectAtIndex:i]];

//bind TEXT...
if([colType isEqualToString:@"TEXT"]){
sqlite3_bind_text(statement, (i + 1), [[row valueForKey:[allKeys objectAtIndex:i]] UTF8String], -1, SQLITE_TRANSIENT);
}
//bind INT...
if([colType isEqualToString:@"INT"]){
sqlite3_bind_int(statement, (i + 1), [[row valueForKey:[allKeys objectAtIndex:i]] intValue]);
}
//bind REAL...
if([colType isEqualToString:@"REAL"]){
sqlite3_bind_double(statement, (i + 1), [[row valueForKey:[allKeys objectAtIndex:i]] floatValue]);
}
//bind BLOB...
if([colType isEqualToString:@"BLOB"]){
NSData *tmpData = [row valueForKey:[allKeys objectAtIndex:i]];
sqlite3_bind_blob(statement, (i + 1), [tmpData bytes], (int)[tmpData length], SQLITE_TRANSIENT);
}
}

//execute if bind went ok...
if(sqlite3_step(statement) != SQLITE_DONE){
[BT_debugger showIt:self message:[NSString stringWithFormat:@"insertRowsIntoTable ERROR: %s", sqlite3_errmsg(sqlite3Database)]];
}

//reset statement...
sqlite3_reset(statement);

}//for...

//execute the batch...
sqlite3_exec(sqlite3Database, "COMMIT TRANSACTION", NULL, NULL, &errorMessage);
sqlite3_finalize(statement);
[self closeDatabase];

}else{
[BT_debugger showIt:self message:[NSString stringWithFormat:@"insertRowsIntoTable ERROR (1) %s", sqlite3_errmsg(sqlite3Database)]];
}//prepare...

}


*** add this method to the BT_database.h file:

-(void)getTabsForApplication:(NSString *)tableName withRows:(NSArray *)rows;


*** appDelegate.m file:

after
NSMutableArray *insertItems = [[NSMutableArray alloc] init];

add this
NSMutableArray *tabItems = [[NSMutableArray alloc]init];

and then...
after
[insertItems addObject:row];
add this
if([thisList isEqualToString:@"BT_tabs"]){
NSLog(@"in tabs list, adding to array");
[tabItems addObject:row];
}


after
//insertItems...
if([insertItems count] > 0){
NSLog(@"there are new items : %lu",(unsigned long)[insertItems count]);

[appDelegate.rootDatabase insertRowsIntoTable:bt_itemsTableName withRows:insertItems];
}

add this

if([tabItems count] > 0){
NSLog(@"doing the tabs in the database");
[appDelegate.rootDatabase getTabsForApplication:bt_itemsTableName withRows:tabItems];
}


Compile, run and then see if that makes a difference.

Remember I'm recommending you do this to a copy of your project and I'm not going to say that this is the right way to go. I'm just saying it worked for me, I am able to update the app via refresh now, it was a case of the database updates not working as expected.

If you do get it to work, please let me know,

Liz
 
AlanMac
Aspiring developer
Profile
Posts: 2435
Reg: Mar 05, 2012
Esher, UK
35,350
like
01/09/17 06:00 AM (1 week ago)
Thanks Liz, I will have a look.

Alan
 
AlanMac
Aspiring developer
Profile
Posts: 2435
Reg: Mar 05, 2012
Esher, UK
35,350
like
01/09/17 08:37 AM (1 week ago)
Implemented the above, it runs OK insof as the app does not crash. However, I added (or tried) to add tab menus, which are not working, correctly. But my original issue, with refresh is exactly he same. But thanks for trying Liz.

Here is the scenario:

App is on my iPhone, not connected to xcode.
My app does not have tabs, home page is menu buttons.

Label for the first menu item is "CustURL".
I change the label in the control panel to "Cust-URL" and save.
I refresh the app - the label does not change (It should).
I close the app and refresh. Label does not change. (It should).
On my iphone I double click the home button and swipe the app away to remove it from memory, launch it again from the icon, hey presto, label has changed (as it should).
 

Login + Screen Name Required to Post

pointerLogin to participate so you can start earning points. Once you're logged in (and have a screen name entered in your profile), you can subscribe to topics, follow users, and start learning how to make apps like the pros.