iOS 7 - Using MLPAutoCompleteTextField with a plain NSArray - ios

I am relatively new to iOS Development and I wanted to implement an autocomplete textfield in my application. Upon doing research, I have come across this library, MLPAutoCompleteTextField. I downloaded it, ran the Demo, and tried to understand how it works.
From what I got, the demo uses a custom class for the Array and a custom cell view that's why the autocomplete in the demo contains the flag of the country.
However, what I want to implement is a much simpler version, one that would only use an Array, no more custom classes for the data and the cell layout.
Here is what I have so far:
My FirstViewController.h File
#import <UIKit/UIKit.h>
#import "MLPAutoCompleteTextFieldDataSource.h"
#import "MLPAutoCompleteTextFieldDelegate.h"
#interface FirstViewController : UIViewController <UITextFieldDelegate, MLPAutoCompleteTextFieldDataSource, MLPAutoCompleteTextFieldDelegate>
#property (strong, nonatomic) NSArray *groupID;
#property (strong, nonatomic) NSMutableArray *part;
#property (strong, nonatomic) NSMutableArray *brand;
#property (strong, nonatomic) NSMutableArray *barcode;
#property (strong, nonatomic) NSMutableArray *itemName;
#property (weak) IBOutlet MLPAutoCompleteTextField *groupIDInput;
#property (weak) IBOutlet MLPAutoCompleteTextField *partInput;
#property (weak) IBOutlet MLPAutoCompleteTextField *brandInput;
#property (weak) IBOutlet MLPAutoCompleteTextField *barcodeInput;
#property (weak) IBOutlet MLPAutoCompleteTextField *itemNameInput;
#property (strong, nonatomic, retain) IBOutlet UIButton *searchButton;
#property (assign) BOOL testWithAutoCompleteObjectsInsteadOfStrings;
#end
As you can see, I have 5 AutoCompleteTextViews and I intend to use the 5 Arrays to supply the data for the autoCompleteTextViews.
This is my FirstViewController.m File:
#import "FirstViewController.h"
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
#import "MLPAutoCompleteTextFieldDataSource.h"
#import "MLPAutoCompleteTextFieldDelegate.h"
#import "MLPAutoCompleteTextField.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize groupID;
#synthesize part;
#synthesize brand;
#synthesize barcode;
#synthesize itemName;
#synthesize groupIDInput;
#synthesize partInput;
#synthesize brandInput;
#synthesize barcodeInput;
#synthesize itemNameInput;
#synthesize searchButton;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setType];
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - MLPAutoCompleteTextField DataSource
- (void)groupIDInput:(MLPAutoCompleteTextField *)textField
possibleCompletionsForString:(NSString *)string
completionHandler:(void (^)(NSArray *))handler{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
NSArray *completions;
if(self.testWithAutoCompleteObjectsInsteadOfStrings){
completions = [self allCountryObjects];
} else {
completions = [self allCountries];
}
handler(completions);
});
}
-(void) setType{
[self.groupIDInput setAutoCompleteTableAppearsAsKeyboardAccessory:NO];
}
- (NSArray *)allCountryObjects{
if(!self.groupID){
NSArray *countryNames = [self allCountries];
NSMutableArray *mutableCountries = [NSMutableArray new];
for(NSString *countryName in countryNames){
[mutableCountries addObject:countryName];
}
[self setGroupID:[NSArray arrayWithArray:mutableCountries]];
}
return self.groupID;
}
- (NSArray *)allCountries{
NSArray *countries =
#[/* Insert Long List of Countries Here */];
return countries;
}
#end
However, my problem now is that in the demo, there is a line that goes [self.autocompleteTextField registerAutoCompleteCellClass:[DEMOCustomAutoCompleteCell class] wherein the custom cell class is used. I get the feeling that I'm also supposed to create my own custom cell class even though I'm not implementing anything fancy.
So, question is:
Do I have to implement my own CustomAutoCompleteObject and CustomAutoCompleteCell? If not, how can I implement this library just by using simple Arrays?
Any help is appreciated. I have been working on this for the past 4-5 hours and my lack of iOS Dev knowledge is taking it's toll on me.
UPDATE 1:
I tried to use a predeclared array instead of a mutable one populated by a database query, I also made some changes as follows:
- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
possibleCompletionsForString:(NSString *)string
completionHandler:(void (^)(NSArray *))handler{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
NSArray *completions;
//completions = [self allCountries];
completions = [self initializeGroupIDArray];
handler(completions);
});
}
This function is attached to the storyboard.
And my initializeGroupIDArray is as follows:
-(NSArray *)initializeGroupIDArray{
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:#"itemList.db"];
NSMutableArray *groupArray = #[/* Insert List of Countries Here */];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSString *sqlSelectQuery = #"SELECT DISTINCT GROUPID FROM ItemList";
// Query result
FMResultSet *resultsWithNameLocation = [database executeQuery:sqlSelectQuery];
while([resultsWithNameLocation next]) {
NSString *queryResult = [NSString stringWithFormat:#"%#",[resultsWithNameLocation stringForColumn:#"GROUPID"]];
// loading your data into the array, dictionaries.
NSLog(#"GroupID = %#", queryResult);
[groupArray addObject:queryResult];
}
[database close];
NSArray *groupID;
[groupID = groupArray copy];
return groupID;
}
However, it seems to me that I am not adding my results from the database query properly. Does anyone have ideas?

I didn't initialize my mutable array. Now goes goes as such:
#pragma mark - MLPAutoCompleteTextField DataSource
- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
possibleCompletionsForString:(NSString *)string
completionHandler:(void (^)(NSArray *))handler{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
NSLog(#"autoCompleteTextField Entered");
NSArray *completions;
completions = [self allGroups];
handler(completions);
});
}
allGroups function:
-(NSArray *)allGroups{
NSLog(#"allGroups Entered");
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:#"itemList.db"];
NSMutableArray *groupArray = [[NSMutableArray alloc] init]; //This bad body right here.
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSString *sqlSelectQuery = #"SELECT DISTINCT GROUPID FROM ItemList";
// Query result
FMResultSet *resultsWithNameLocation = [database executeQuery:sqlSelectQuery];
while([resultsWithNameLocation next]) {
NSString *groupIDName = [NSString stringWithFormat:#"%#",[resultsWithNameLocation stringForColumn:#"GROUPID"]];
// loading your data into the array, dictionaries.
NSLog(#"Group ID = %#", groupIDName);
[groupArray addObject:groupIDName];
}
[database close];
NSLog(#"size of groupArray (mutbale): %d", [groupArray count]);
for (NSUInteger i = 0; i < [groupArray count]; i++){
NSLog(#"Group Array (mutable) :%#", groupArray[i]);
}
NSArray *groupID;
[groupID = groupArray copy];
NSLog(#"size of groupID (immutbale): %d", [groupID count]);
for (NSUInteger i = 0; i < [groupID count]; i++){
NSLog(#"Group ID (non mutable) :%#", groupID[i]);
}
NSLog(#"allGroups before return statement");
return groupID;
}

Related

My application crashes with this error - 'NSInvalidArgumentException'

I have created a program to retrieve JSON file and it achieved it
NSString *FilePath = [[NSBundle mainBundle]pathForResource:#"Message" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:FilePath];
NSError *error;
if(error){
NSLog(#"Error and CAn't retrive data: %#", error.localizedDescription);
}else{
NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(#"Your Json Dictionary values are %#", jsonDict);
for(NSDictionary *valuesDictionary in jsonDict){
ShopCollectionObject *shopObject = [[ShopCollectionObject alloc]initWithID:[[valuesDictionary objectForKey:#"message_id"]integerValue] Name:[valuesDictionary objectForKey:#"product"] TimeAsPrice:[[valuesDictionary objectForKey:#"message_time"]integerValue] Avathar:[valuesDictionary objectForKey:#"item_image"] user:[valuesDictionary objectForKey:#"user_image"] Name_User:[valuesDictionary objectForKey:#"user_name"] LocationOfUser:[valuesDictionary objectForKey:#"locate_user"]];
But My app crashes here with the above error
[self.objectForArray addObject:shopObject];
}
}
Updated my shop collection code below
Shopcollection object.h
#import <Foundation/Foundation.h>
#interface ShopCollectionObject : NSObject
-(instancetype) initWithID: (int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int) GivenTimeAsPrice Avathar:(NSString *) PhotoOfAvathar user:(NSString *)UserAvathar Name_User: (NSString *) UserNames LocationOfUser:(NSString *) USerLocationGiven;
#property (nonatomic) int msgID;
#property(nonatomic, strong)NSString* Name;
#property (nonatomic) int TimeAsPrice;
#property (nonatomic,strong) NSString* Avathar;
#property (nonatomic,strong) NSString* user;
#property (nonatomic,strong) NSString* Name_User;
#property(nonatomic,strong) NSString* LocationOfUser;
#end
Shopcollectionobject.m
#import "ShopCollectionObject.h"
#implementation ShopCollectionObject
-(instancetype)initWithID:(int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int)GivenTimeAsPrice Avathar:(NSString *)PhotoOfAvathar user:(NSString *)UserAvathar Name_User:(NSString *)UserNames LocationOfUser:(NSString *)USerLocationGiven{
self = [super init];
if(self){
self.msgID = msgID;
self.Name = Profile_name;
self.TimeAsPrice = GivenTimeAsPrice;
self.Avathar = PhotoOfAvathar;
self.user = UserAvathar;
self.Name_User = UserNames;
self.LocationOfUser = USerLocationGiven;
}
return self;
}
#end
You likely aren't initializing your objectForArray. So when you try to call addObject, it's calling it on a null object.
ShopCollectionObject.h
#import <Foundation/Foundation.h>
#interface ShopCollectionObject : NSObject
#property (nonatomic) int message_id;
#property (strong, nonatomic) NSString *Name;
#property (nonatomic) int TimeAsPrice;
#property (strong, nonatomic) NSString *Avathar;//user,Name_User,LocationOfUser,message_id
#property (strong, nonatomic) NSString *user;
#property (strong, nonatomic) NSString *Name_User;
#property (strong, nonatomic) NSString *LocationOfUser;
-(instancetype) initWithID: (int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int) GivenTimeAsPrice Avathar:(NSString *) PhotoOfAvathar user:(NSString *)UserAvathar Name_User: (NSString *) UserNames LocationOfUser:(NSString *) USerLocationGiven;
#property (nonatomic) int msgID;
#end
ShopCollectionObject.m
#import "ShopCollectionObject.h"
#implementation ShopCollectionObject
-(instancetype)initWithID:(int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int)GivenTimeAsPrice Avathar:(NSString *)PhotoOfAvathar user:(NSString *)UserAvathar Name_User:(NSString *)UserNames LocationOfUser:(NSString *)USerLocationGiven{
self = [super init];
if(self){
self.msgID = msgID;
self.Name = Profile_name;
self.TimeAsPrice = GivenTimeAsPrice;
self.Avathar = PhotoOfAvathar;
self.user = UserAvathar;
self.Name_User = UserNames;
self.LocationOfUser = USerLocationGiven;
}
return self;
}
#end
ViewController.m
#import "ViewController.h"
#import "ShopCollectionObject.h"
#interface ViewController ()
{
NSMutableArray *objectForArray;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
objectForArray = [[NSMutableArray alloc]init];
NSString *FilePath = [[NSBundle mainBundle]pathForResource:#"Message" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:FilePath];
NSError *error;
if(error){
NSLog(#"Error and CAn't retrive data: %#", error.localizedDescription);
}else{
NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
for(NSDictionary *valuesDictionary in jsonDict){
ShopCollectionObject *shopObject = [[ShopCollectionObject alloc]initWithID:[[valuesDictionary objectForKey:#"message_id"]intValue] Name:[valuesDictionary objectForKey:#"product"] TimeAsPrice:[[valuesDictionary objectForKey:#"message_time"]intValue] Avathar:[valuesDictionary objectForKey:#"item_image"] user:[valuesDictionary objectForKey:#"user_image"] Name_User:[valuesDictionary objectForKey:#"user_name"] LocationOfUser:[valuesDictionary objectForKey:#"locate_user"]];
[objectForArray addObject:shopObject];
}
NSLog(#"%#",objectForArray);
ShopCollectionObject *data = objectForArray[0];
NSLog(#"%#",data.Name);
}
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
pls check this code

Save NSMutableArray of NSStrings to disk

I have a NSMutableaArray of NSString objects. So i'm using NSKeyedArchiever to save it to disk. So when i try to use
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.EventsList forKey:#"Events"];
}
i got an error
Event encodeWithCoder:]: unrecognized selector sent to instance 0x7fd06b542780
Here's my parts of code:
//-------------------Events.h--------------------------
#interface Event : NSObject
#property (strong,nonatomic) NSString *nameOfEvent;
#property (strong,nonatomic) NSString *dateOfEvent;
#property (strong,nonatomic) NSString *placeOfEvent;
#property int priorityOfEvent;
#end
//---------------Singleton.h ----------------
#interface GlobalSingleton : NSObject <NSCoding, NSCopying> {
NSMutableArray *EventsList;
}
#property (nonatomic,retain) NSMutableArray *EventsList;
+(GlobalSingleton *)sharedFavoritesSingleton;
#end
//----------------Singleton.m------------------------
....
#implementation GlobalSingleton
#synthesize EventsList;
....
....
- (void)encodeWithCoder:(NSCoder *)aCoder {
NSLog (#"%#",EventsList); // not nil
[aCoder encodeObject:self.EventsList forKey:#"Events"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super init])) {
NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:[aDecoder decodeObjectForKey:#"Events"]];
self.EventsList = temp;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
GlobalSingleton *copy = [[GlobalSingleton allocWithZone:zone] init];
copy.EventsList = self.EventsList;
return copy;
}
#end
I get textdata from Web-server using ASIFormDataRequest in JSON format, and then i add this object to NSMutableArray, which is also a Singleton, so it looks like this:
NSDictionary *responseDict = [responseString JSONValue];
GlobalSingleton *Singleton = [GlobalSingleton sharedFavoritesSingleton];
for (NSDictionary *str in responseDict) {
Event *newEvent = [[Event alloc] init];
newEvent.nameOfEvent = [str objectForKey:#"EventName"];
newEvent.dateOfEvent = [str objectForKey:#"EventDate"];
newEvent.placeOfEvent = [str objectForKey:#"EventPlace"];
[Singleton.EventsList addObject:newEvent];
}
//------------------Save this data stored in NSMutableArray to disk-------------------------
[NSKeyedArchiver archiveRootObject:Singleton toFile:[self save_path]];
So, again, execution stops on this:
[aCoder encodeObject:self.EventsList forKey:#"Events"];
But when i try to code single NSString object everything goes with no errors.
eventList doesn't contain NSStrings, it contains Event objects.
Your Event class needs to implement encodeWithCoder: - as the exception message says, the Event class doesn't implement this method.
Also you should use a lowercase s for singleton as it is an instance, not a class, and you should probably not use singletons.

Create MutableArray and add some NSArrays containing Objects

I'm currently learning some objective C but still have problems with the syntax and creating objects.
The Situation: I need a two dimensional "personsArray" which contains many personArrays each containing a NSString *name and a NSNumber *amount (double). Finally I want to calculate some stuff with the array data in another view but I'm far apart from that..
My Plan: Creating a NSMutable Object when the program starts. If I click the Button "Add Person", it creates a personArray with two fixed values (later it should grab those of textAreas). Here is my Code:
Person.h
#import <Foundation/Foundation.h>
#interface Person : NSObject{
NSNumber *amount;
NSString *name;
}
- (void) createPersonArray:(double)theAmount withName:(NSString*) aName;
#end
Person.m
#import "Person.h"
#implementation Person
- (void) createPersonArray:(NSNumber*)theAmount withName:(NSString*) aName{
NSArray* personArray = [NSArray arrayWithObjects:theAmount,aName,nil];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak,nonatomic) IBOutlet NSMutableArray *personsArray;
- (IBAction)addPerson:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "Person.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction)addPerson:(id)sender {
Person *newPerson;
newPerson = [Person new];
[newPerson createPersonArray:100.00 withName:#"test"];
[_personsArray addObject:newPerson];
}
#end
I know that this wont work, but I don't know how to realize the stuff that I described above. If I build the program, the app starts. if I click the button the debugger jumps to the createPersonArray and outputs "Thread 1: EXC_BAD_ACCESS (code=1,address=0x40590000] and "Unused variable 'personArray'".
I watched many tutorials know but none of them explained this situation.. How must my code be structured to accomplish my goal? Am I on the right path or is it the wrong approach?
greetings
I think if you want save array to MutableArray, you only need create method in ViewController. If you create Person.h, i suggest you should save to MutableArray is Person Object. You can use code below:
Person.h:
#property (nonatomic, strong) NSNumber *amount;
#property (nonatomic, strong) NSString *name;
instead:
NSNumber *amount;
NSString *name;
Person.m:
#implementation Person
#synthesize name;
#synthesize amount;
- (void) createPersonArray:(double)theAmount withName:(NSString*) aName{
amount = [NSNumber numberWithDouble:theAmount];
name = aName;
}
ViewController.h
#property (strong,nonatomic) NSMutableArray *personsArray;
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
_personsArray = [[NSMutableArray alloc]init];
}
- (IBAction)addPerson:(id)sender {
Person *newPerson;
newPerson = [Person new];
[newPerson createPersonArray:100.00 withName:#"test"];
[_personsArray addObject:newPerson];
}
If you don't understand. You can comment below, i will help you.
When you need get contain, you can use:
for (Person *person in _personsArray){
NSLog(#"Amount: %# \n Name: %# \n ",ps.amount,ps.name,);
}
or
for (int i = 0; i< [_personsArray count]; i++){
Person *ps = [_personsArray objectAtIndex:i];
NSLog(#"Amount: %# - Name:%#",ps.amount,ps.name);
}
================================== UPDATE ===========================
double sumAmount = 0;
for (int i = 0; i < [_personsArray count]; i++){
Person *person = [_personsArray objectAtIndex:i];
sumAmount = sumAmount + [person.amount doubleValue];
}
double averageAmount = sumAmount / [_personsArray count];
NSLog(#"%f",averageAmount);
First, personsArray variable is not a outlet. So, remove outlet property and replace weak with strong:
#property (strong,nonatomic) NSMutableArray *personsArray;
Second, need to initialize NSMutableArray before using it, maybe in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
_personsArray = [NSMutableArray new];
}

How to load/save data in NSMutableArray

Here is my mainAppDelegate.h:
#import <UIKit/UIKit.h>
#interface mainAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property NSMutableArray *toDoItems;
#end
and my mainAppDelegate.m:
#import "mainAppDelegate.h"
#implementation mainAppDelegate
- (void)applicationWillTerminate:(UIApplication *)application
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"toDoItems.plist"];
[self.toDoItems writeToFile:filePath atomically:TRUE];
}
#end
I have another file, XYZToDoListViewController.m with the code:
#import "XYZToDoListViewController.h"
#import "XYZToDoItem.h"
#import "XYZAddItemViewController.h"
#interface XYZToDoListViewController ()
#property NSMutableArray *toDoItems;
#end
#implementation XYZToDoListViewController
- (IBAction)unwindToList:(UIStoryboardSegue *)segue
{
XYZAddItemViewController *source = [segue sourceViewController];
XYZToDoItem *item = source.toDoItem;
if (item != nil) {
[self.toDoItems addObject:item];
[self.tableView reloadData];
}
}
- (IBAction)clearData:(UIBarButtonItem *)sender;
{
[self.toDoItems removeAllObjects];
[self.tableView reloadData];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.toDoItems = [[NSMutableArray alloc] init];
self.navigationController.view.backgroundColor =
[UIColor colorWithPatternImage:[UIImage imageNamed:#"bg_full.png"]];
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.contentInset = UIEdgeInsetsMake(-35, 0, -35, 0);
}
#end
This is at least what I think is relevant. My basic framework is something I followed from this tutorial. So as you can see I have an NSMutableArray named .toDoItems. and I want it to remember the list when I exit the application (not just minimizing it; it does that already. I think I have the code which is saving the data, but what do I use to check if the file exists, and if so, display it?
And would this affect my clearData method when the app resumes as well?
As if i understood true you want to save your NSMutableArray even after restart your app.
So you may use this codes to save your NSMutableArray with NSUserDefaults.
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaultsPhoneId setObject:yourArray forKey:#"yourKey"];
[defaultsPhoneId synchronize];
And it is how you can take it back
yourArray=[[NSMutableArray alloc]initWithArray:[[NSUserDefaults standardUserDefaults]objectForKey:#"yourKey"]];
But dont forget to initialize it before save with NSUserDefaults.
By the way you may check yourArray anytime if it is loaded or not with
if([yourArray count]==0){
//Your array is empty so you have to call it with #"yourKey". (second codes part)
}
"what do I use to check if the file exists"
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:your_file_path])
"..and if so, display it?"
Please read about UITableView and UITableViewDataSource
https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html
"And would this affect my clearData method when the app resumes as well?"
clearData is a button action. It will be called only if user will tap
a button. It is not connected with application launch/stopping.

Can't add entry to NSMutableDictionary in singleton

I have a singleton with an NSMutableDictionary in it. I want to add an entry to that dictionary from one of my views. For a reason that I can't comprehend it's not working and I'm receiving the 'NSDictionary setObject:forKey: unrecognized selector sent to instance' error. This doesn't seem like it should be so hard but I can't find an answer to the problem.
So I've wired up a button in my .xib to call the createKey method and kablooey. I've also tested to ensure that the dictionary exists and it does.
Here's my singleton header:
#import <Foundation/Foundation.h>
#interface SharedAppData : NSObject <NSCoding>
{
NSMutableDictionary *apiKeyDictionary;
}
+ (SharedAppData *)sharedStore;
#property (nonatomic, copy) NSMutableDictionary *apiKeyDictionary;
-(BOOL)saveChanges;
#end
My singleton implementation (important bits)
#interface SharedAppData()
#end
#implementation SharedAppData
#synthesize apiKeyDictionary;
static SharedAppData *sharedStore = nil;
+(SharedAppData*)sharedStore {
#synchronized(self){
if(sharedStore == nil){
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *testFile = [documentsDirectory stringByAppendingPathComponent:#"testfile.sav"];
Boolean fileExists = [[NSFileManager defaultManager] fileExistsAtPath:testFile];
if(fileExists) {
sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:testFile];
}
else{
sharedStore = [[super allocWithZone:NULL] init];
}
[sharedStore setSaveFile:testFile];
}
return sharedStore;
}
}
- (id)init {
if (self = [super init]) {
apiKeyDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
In my view controller header...
#import <UIKit/UIKit.h>
#import "SharedAppData.h"
#interface AddKeyViewController : UIViewController <UITextFieldDelegate>
{
UIButton *addKey;
}
#property (weak, nonatomic) IBOutlet UITextField *apiName;
#property (weak, nonatomic) IBOutlet UITextField *apiKey;
-(IBAction)createKey:(id)sender;
#end
View controller implementation:
#import "AddKeyViewController.h"
#import "SharedAppData.h"
#interface AddKeyViewController ()
#end
#implementation AddKeyViewController
#synthesize apiName, apiKey, toolbar;
-(IBAction)createKey:(id)sender {
NSString *name = [apiName text];
NSString *key = [apiKey text];
[[[SharedAppData sharedStore] apiKeyDictionary] setObject:key forKey:name];
}
#end
Your apiKeyDictionary property is set to copy. That will send the copy message to the NSMutableDictionary instance you create in your init method - returning not an NSMutableDictionary but an NSDictionary. Change it to strong or retain instead.
I suspect that the problem is with your property being "copy" rather than "strong"; when you set it, mutanle dictionsry gets copied into an immutable one.
Try changing your property to "strong".

Resources