Refresh View and Data everytime app opens - ios

I have a TableView that needs to be refreshed every time the app opens, but I can't get it to do that.
The reason for this, is that there is new data for every day stored in a JSON file, so the app needs to refresh to find out if its a new day so it can load the new data.
I tried moving my code from viewDidLoad to viewWillAppear thinking that would do the trick, but it didn't.
Any ideas?
ViewController.m
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Get current date, remove year from current date
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
NSString *dateToday = [formatter stringFromDate:[NSDate date]];
NSString *dateTodayShort = [dateToday substringToIndex:[dateToday length] -6];
// Get JSON file path
NSString *JSONFilePath = [[NSBundle mainBundle] pathForResource:#"Days" ofType:#"json"];
NSData *JSONData = [NSData dataWithContentsOfFile:JSONFilePath];
NSDictionary *JSONDictionary = [NSJSONSerialization JSONObjectWithData:JSONData options:kNilOptions error:nil];
days = JSONDictionary[#"days"];
// Iterate thru JSON to find Data for Today
NSObject *todayJson;
for (NSObject *object in days) {
NSString *dateObject = [object valueForKey:#"day"];
if ([dateObject isEqualToString:dateTodayShort]) {
todayJson = object;
NSString *textToday = [todayJson valueForKey:#"text"];
NSString *backgroundImageToday = [todayJson valueForKey:#"backgroundImage"];
textGlobal = textToday;
backgroundImageGlobal = backgroundImageToday;
}
}
// Other set up code...
}

I had a similar issue recently, my misunderstanding was that viewWillAppear / viewDidAppear would be called whenever the app opens (and the corresponding view controller is shown). That is in fact no the case!
How you do this is by adding an observer for a NSNotification like so:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateData) name:UIApplicationDidBecomeActiveNotification object:nil];
iOS sends a system NSNotification when your app is launched. The name of the notification is held in the constant UIApplicationDidBecomeActiveNotification. You can add your UITableViewController that holds the data (or any other class for that matter) as an observer for that notification and perform the update whenever the notification is received.

Related

See the variable in the same method=null ios

I use library soap the return of this function in on nsdictionary i change it into nsarray after i close ];} and type nslog it give that nsarray =null but if i put it before close of the method in the method give data
- (void)showlinks
{
SYSoapClient *show_links_obj = [SYSoapClient new];
links_tags = [[NSMutableArray alloc] initWithObjects:#"empid", #"type", nil];
links_vars = [[NSMutableArray alloc] initWithObjects:txt_username, type_user, nil];
[show_links_obj callSoapServiceWithParameters__functionName:#"getlinks"
tags:links_tags
vars:links_vars
callback:^(NSDictionary *result,
BOOL response)
{
link_raw_Data = [result allValues];
link_con_Data = [link_raw_Data componentsJoinedByString:#""];
//NSArray *links = [con_Data componentsSeparatedByString:#"#"];
links = [link_con_Data componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"#^"]];
NSUInteger x = links.count;
NSLog(#"%#",link_raw_Data);
//NSLog(#"%d",x);
//NSLog(#"%#",links[5]);
}];
NSLog(#"%#",links[5]);
}
Judging by the callback argument to the soap service, it's an asynchronous call. This means that it will return right away, do the networking on a background thread and call the callback sometime later when it is done.
Since it's asynchronous and doesn't wait/block, the log statement just after it will be executed before getting any data back from the soap service.

UIButton Title not updating all the time

I am programmatically changing the title of a UIButton to display count of items in a NSMutableArray.
Sometimes, the title does not update as I add items to the array. When I do the NSLog of what the title should be, it is correct but the button title does not update all the time.
Can anyone spot a problem with my code?
- (void) refreshAfterBlueToothScan
{
/*************************************Refresh Displayed Total********************/
//[_manualBCtemporaryCartArray26 removeAllObjects];
//_manualBCtemporaryCartArray26 = [[NSMutableArray alloc] init];
[localTempArray removeAllObjects];
if (!localTempArray)
{
localTempArray = [[NSMutableArray alloc] init];
}
// Get the DBAccess object;
DBAccess *dbAccess1 = [[DBAccess alloc] init];
// Get the products array from the database
//Get the latest NSMutableArray
localTempArray = [dbAccess1 getProductsFromTmpSales];
// Close the database because we are finished with it
[dbAccess1 closeDatabase];
//Count How many products in array
int iNumberofArrayProducts;
iNumberofArrayProducts = [localTempArray count];
NSString* productCount = [NSString stringWithFormat:#"%i", iNumberofArrayProducts];
NSLog(#"The NUMBER OF TmpTable PRODUCTS is %#",productCount);
//Sum the selling price of the records in the _manualBCtemporaryCartArray26
amountSum = [localTempArray valueForKeyPath:#"#sum.lTotalSellingPrice"];
NSLog(#"The total TmpTable SELLING PRICE is %#",amountSum);
NSNumberFormatter * formatter = [[NSNumberFormatter alloc]init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:2]; // Set this if you need 2 digits
[formatter setMinimumFractionDigits:2]; // Set this if you need 2 digits
NSString * newString = [formatter stringFromNumber:[NSNumber numberWithFloat:[amountSum floatValue]]];
NSLog(#"FORMATTED MONTHLY SALES IS,R%#",newString);
//This is a hack that replaces the comma with a dot. I want to display the Price as R2 000.10
NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:#"/:,"];
newString=[[newString componentsSeparatedByCharactersInSet: doNotWant] componentsJoinedByString: #"."];
NSString *item = [NSString stringWithFormat:#"R%# (%i)",newString, iNumberofArrayProducts];
/**********Play audio to warn user that item was added to cart*******/
// ivar
SystemSoundID mBeep;
// Create the sound ID
NSString* path = [[NSBundle mainBundle]
pathForResource:#"scanBarCode" ofType:#"mp3"];
NSURL* url = [NSURL fileURLWithPath:path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &mBeep);
// Play the sound
AudioServicesPlaySystemSound(mBeep);
// Dispose of the sound
//AudioServicesDisposeSystemSoundID(mBeep);
/**********END - Play audio to warn user that item was added to cart*******/
//When user scans the barcode, we want to display the product that was just scanned. This allows user to see what product they just scanned as it is automatically loaded on the shopping cart. Put IF Statement so this code only executes after the scanning barcode.
[self.searchDisplayController setActive: YES animated: YES];
//self.searchDisplayController.searchBar.hidden = NO;
self.searchDisplayController.searchBar.text = [NSString stringWithFormat:#"%i",fklInventoryID];
[self.searchDisplayController.searchBar becomeFirstResponder];
[self.searchDisplayController.searchBar resignFirstResponder];
NSLog(#"BUTTON ITEM IS,%#",item);
[manualTotalPriceBtn setTitle: item forState: UIControlStateNormal];
/*************************************END - Refresh Displayed Total********************/
}
Try this:
[manualTotalPriceBtn setAttributedTitle:nil forState:UIControlStateNormal];
[manualTotalPriceBtn setTitle:item forState:UIControlStateNormal];
If you are using a xib file the IB will set your value for the attributedTitle instead of the title.
try changing button type from system to custom.
Check that you update the button on the mainthread. If your method is called from a callback of whatever bluetooth scanner module you are using, it might be happening on a backround thread. This will cause button to sometimes update, sometimes it will not, or later.
If not, check the superview property of the button to not be nil. Maybe somewhere in your code you create a bew button, add it to the superview but forgot update your property to point to it (or some other scenario where you update a button that is not inserted in the view).

Global NSDate variable seems to make app crash

I have a global variable in FirstViewController.h
extern NSString *dateString;
it records the date/time of when I press saveText button. There is another button called readText which pushes a UITableView. The first cell on this table will print the date saved.
However, this only works if I first press the saveText button. Otherwise, if I just press readText, it crashes. How can I get it so that if there is no current datetime saved, that it doesn't crash?
Here is where I wrote the timestamp for saveButton:
-(IBAction)saveText:(id)sender{
//code to save text, irrelevant to the question//
dateString = [NSDateFormatter localizedStringFromDate:[NSDate date]
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
NSLog(#"%#",dateString);
}
and here is the code to load the tableviewcells with the timestamp
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *str = #"Text- saved on: ";
str = [str stringByAppendingString: dateString];
self.list = [[NSArray alloc] initWithObjects: str, nil];
}
In my methods that use the variable dateString,
I used:
if([dateString length] == 0){
//perform standard procedure
}
else {
//what I want it to do
}

Does NSCache persist across ViewControllers?

Its my first time using NSCache and I know that it doesn't persist on app lunch.
But does it persist across ViewControllers?... Meaning... If I set the cache object on ViewController A and then I move to ViewController B can I still access it?
My question is related to an issue that I am having in my code. I am on ViewController B and I set the cache object. Then move to ViewController B and try to retrieve that object but is never found.
Is that normal or there is a problem in my code??? My Views are quite inexpensive so I see no reason why it would be dropping the cache object
ViewController A (Using Cache)
- (void) searchDone:(NSDictionary*)response {
NSString * str = input.text;
str = [str stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString* cachedKey = [str stringByReplacingOccurrencesOfString:#"#" withString:#""];
cachedKey = [cachedKey lowercaseString];
//
// Cache
//
NSCache * cache = [[NSCache alloc]init];
NSDictionary* chachedData = [cache objectForKey:cachedKey];
// Check for a cached version of this
if ( chachedData ) {
NSLog(#"There is a cache");
NSTimeInterval timeDifferenceBetweenDates = [chachedData[#"time"] timeIntervalSinceNow];
CGFloat time = fabsf(timeDifferenceBetweenDates);
if ( time < sysTraditionalSearchCacheTime ) {
NSLog(#"using cache");
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:input.text,#"input",chachedData,#"response",nil];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"closeSearch"
object:nil
userInfo:dictionary];
return;
}
[cache removeObjectForKey:cachedKey];
}
ViewController B (Cache Setter)
- (void) notificationCloseSearch:(NSNotification*) notification {
input.text = [[notification userInfo] valueForKey:#"input"];
NSDictionary* response = [[notification userInfo] valueForKey:#"response"];
NSString * str = input.text;
str = [str stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString* cachedKey = [str stringByReplacingOccurrencesOfString:#"#" withString:#""];
cachedKey = [cachedKey lowercaseString];
//
// Cache
//
NSCache * cache = [[NSCache alloc]init];
NSDictionary* chachedData = [cache objectForKey:cachedKey];
// Check for a cached version of this
if ( chachedData ) {
NSTimeInterval timeDifferenceBetweenDates = [chachedData[#"time"] timeIntervalSinceNow];
CGFloat time = fabsf(timeDifferenceBetweenDates);
if ( time >= sysTraditionalSearchCacheTime ) {
[cache removeObjectForKey:cachedKey];
}
} else { // if there is no cache then set one
NSLog(#"setting cache key %#",cachedKey);
NSDate* now = [NSDate date];
NSMutableDictionary* newResopnse = [[NSMutableDictionary alloc]initWithDictionary:response];
[newResopnse setObject:now forKey:#"time"];
response = [[NSDictionary alloc] initWithDictionary:newResopnse];
[cache setObject:response forKey:cachedKey];
NSLog(#"cached %#",[cache objectForKey:cachedKey]);
}
}
NSCache is a some kind of NSMutableDictionary.
The difference is that when NSCache detects excessive memory pressure it will release some of it key-value pairs.
In ViewControllerA you create NSCache object
NSCache * cache = [[NSCache alloc]init];
And in ViewControllerB you create one more NSCache object again
NSCache * cache = [[NSCache alloc]init];
So it will be two different objects with two different set of key-value pairs.
If you need some kind of storage you can write singleton class which will contain one NSCache object.

IOS: read txt file when I launch an app

Everytime I launch an app, I should to read 5 txt file where are stored some information; then the methods that read and stored data in array from these file should be write in my firstview controller (class of my first view) or in class appdelegate?
In the relevant view controller (probably viewDidLoad).
It would look something like this (untested):
- (void)viewDidLoad {
NSArray *fileNames = [NSArray arrayWithObjects:#"fileName1.txt", #"fileName2.txt", #"etc", nil];
NSMutableArray *fileStrings = [[NSMutableArray alloc] init];
for (int i = 0; i<[fileNames count]; i++) {
NSString *aFileName = [fileNames objectAtIndex:i];
NSString *aFilePath = [[NSBundle mainBundle] pathForResource:aFileName];
NSString *aFileContents = [[NSString alloc] initWithContentsOfFile:aFilePath];
[fileStrings addObject:aFileContents];
[aFileContents release];
}
myStrings = fileStrings; // Some array to store to
}
I am guessing this is configuration info that you are reading. I would suggest using a pList instead of using text files.
Apple has really optimized reading from & to a plist. Hope this helps...

Resources