Passing newMangagedObject - ios

i'm trying to pass the newManagedObject to another viewcontroller, so i can make a relationship between my Song and Playlist entity.
Here i'm saving my object:
-(void)saveTap:(id)sender{
newManagedObject = (Playlists*)[NSEntityDescription insertNewObjectForEntityForName:#"Playlists" inManagedObjectContext:_managedObjectContext];
[newManagedObject setValue:self.textfield.text forKey:#"playlistName"];
// Save the context.
NSError *error = nil;
if (![_managedObjectContext save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
[self fetchDevices];
}
fetchDevices method:
- (void)fetchDevices {
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Playlists"];
devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableViewData reloadData];
}
On select i pass the newManagedObject to my Singleton [rowNumber singleObj]
The problem is that it returns nil instead of the playlistName. How can implement indexpath.row, so it will return the selectedRow playlistName.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
newManagedObject = (Playlists*)[NSEntityDescription insertNewObjectForEntityForName:#"Playlists" inManagedObjectContext:_managedObjectContext];
optionsSingle = [rowNumber singleObj];
optionsSingle.selectedRowNow = newManagedObject;
NSLog(#"%#", optionsSingle.selectedRowNow);
SongsViewController *songsViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SongsViewController"];
[self.navigationController pushViewController:songsViewController animated:YES];
}

If devices is your Fetched Results Controller then you should be able to get the record that corresponds to the row that was clicked using:
[devices objectAtIndexPath:indexPath.row];

Related

Inconsistency in Saving/Fetching Data in Core Data

My first post here, getting straight to the point.
I'm facing a problem and I'm not sure whether is with saving of data or fetching it.
Here are my codes where I tried to save the data in my Entity, "Sequence". The entity consists of 2 attributes "seqForWk1CD" & "seqForWk2CD".
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
SequenceMO *seqEntity = [NSEntityDescription
insertNewObjectForEntityForName:#"Sequence"
inManagedObjectContext:context];
// some other code
seqEntity.seqForWk1CD = arrForWk1;
seqEntity.seqForWk2CD = arrForWk2;
NSLog(#"%#", arrForWk1);
NSLog(#"%#", arrForWk2);
NSError *error = nil;
if (context != nil) {
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
When printed, the arrays will always display the contents of the array.
This is where I try to fetch the data.
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Sequence" inManagedObjectContext:context];
[request setEntity:entity];
NSError *error;
if(![context save:&error]){
NSLog(#"Error fetching. %# %#", error, [error localizedDescription]);
}
NSUInteger count = [context countForFetchRequest:request error:&error];
if(count != 0){
NSArray *fetchObj = [context executeFetchRequest:request error:&error];
NSManagedObject *sequence = (NSManagedObject *)[fetchObj objectAtIndex:0];
NSLog(#"1 - %#", sequence);
arrForWk1 = [sequence valueForKey:#"seqForWk1CD"];
NSLog(#"%#", arrForWk1);
arrForWk2 = [sequence valueForKey:#"seqForWk2CD"];
NSLog(#"%#", arrForWk2);
}
The problem comes when I restart the application. The arrays either show (null) for both arrays or it shows the contents of both of the arrays. The if statement for if(![context save:&error]) never gets triggered. Subclasses of NSManagedObject for the entity has already been added.I've also tried declaring the AppDelegate in #interface and forced to save the context immediately by doing [delegate saveContext];.Here is the method where the saving happens. "check" is initialized to 0 at the viewDidLoad method. Both "arrForWk1" & "arrForWk2" are declared at #interface.
- (IBAction)randomizeSequence:(UIButton *)sender {
NSMutableArray *storeArray = [[NSMutableArray alloc] init];
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
SequenceMO *seqEntity = [NSEntityDescription insertNewObjectForEntityForName:#"Sequence" inManagedObjectContext:context];
BOOL record = NO;
int x;
for (int i=0; [storeArray count] < 9; i++) //Loop for generate different random values
{
x = 1 + arc4random() % 9;//generating random number
if(i==0)//for first time
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
else
{
for (int j=0; j<= [storeArray count]-1; j++)
{
if (x ==[[storeArray objectAtIndex:j] intValue])
record = YES;
}
if (record == YES)
{
record = NO;
}
else
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
}
}
check++;
if(check == 1 ) {
arrForWk1 = storeArray;
[self.wk1Seq reloadData];
}
else if(check == 2) {
arrForWk2 = storeArray;
seqEntity.seqForWk1CD = arrForWk1;
seqEntity.seqForWk2CD = arrForWk2;
NSError *error = nil;
if (context != nil) {
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
[self.wk2Seq reloadData];
}
Just to add on, the arrays are of data type NSMutableArray and I'm trying to store them into attributes of type "Transformable".
After researching around I managed to solve the problem. I'm not sure how it actually works but I solved it by rearranging the code when I'm trying to fetch the data.
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSEntityDescription *descriptor = [NSEntityDescription entityForName:#"Sequence" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
request.entity = descriptor;
NSError *error;
NSArray *fetchObj = [context executeFetchRequest:request error:&error];
if(fetchObj == nil) {
NSLog(#"Error occured when trying to fetch.");
}
else {
if(fetchObj.count == 0) {
NSLog(#"No objects saved");
else {
NSManagedObject *sequence = (NSManagedObject *)[fetchObj objectAtIndex:0];
NSLog(#"1 - %#", sequence);
arrForWk1 = [sequence valueForKey:#"seqForWk1CD"];
NSLog(#"%#", arrForWk1);
arrForWk2 = [sequence valueForKey:#"seqForWk2CD"];
NSLog(#"%#", arrForWk2);
NSLog(#"2 - %#", sequence);
}
I've tried also tried 2 ways of saving the data. In the if statement where I tried to save the data, I converted the NSMutableArrays to NSArrays.
else if(check == 2) {
test2 = storeArray;
NSManagedObjectContext *context = [delegate managedObjectContext];
SequenceMO *seqEntity = [NSEntityDescription insertNewObjectForEntityForName:#"Sequence" inManagedObjectContext:context];
NSArray *tArr = [arrForWk1 copy];
NSArray *tArr2 = [arrForWk2 copy];
seqEntity.seqForWk1CD = tArr;
seqEntity.seqForWk2CD = tArr2;
NSError *error = nil;
if (context != nil) {
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
The second way I tried is by using an answer from Core Data not saving changes to Transformable property
id temp = [seqEntity seqForWk1CD];
id temp2 = [seqEntity seqForWk2CD];
temp = arrForWk1;
temp2 = arrForWk2;
[seqEntity setSeqForWk1CD:temp];
[seqEntity setSeqForWk2CD:temp2];
Apparently it worked somehow.

Core Data not saving an incremented integer

I'm making a SpriteKit game and I need to save the player's score using Core Data. I have a property with int value that starts off as being set to "5" and increment it x amount of times. I save it then transition to a different scene and fetch it. It shows up un-incremented with the initial value of "5".
I'm new to Core Data so forgive me if this is a stupid question, but how can I get Core Data to take the incrementation in to account? Or Is information being lost when I reference the property and how can I prevent this?
self.score = 5;
self.score++
and then save by calling this method.
AppDelegate.m
-(void) createObject {
Score *scoreEntity = (Score *)[NSEntityDescription
insertNewObjectForEntityForName:#"Score"
inManagedObjectContext:self.managedObjectContext];
SpaceshipScene *spaceshipSceneReference = [[SpaceshipScene alloc] init];
id points = [NSNumber numberWithInteger: spaceshipSceneReference.score];
scoreEntity.points = points;
scoreEntity.playerName = #"Joe";
NSError *error = nil;
// Saves the managedObjectContext
if (! [[self managedObjectContext] save:&error] ) {
NSLog(#"An error! %#", error);
}
}
This is how I call it.
SpaceshipScene.m
AppDelegate *appDelegateReference = [[AppDelegate alloc] init];
[appDelegateReference createObject];
I then fetch it in another class/scene using this method
AppDelegate.m
-(void)fetchObject {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Score"inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Sort fetched data
NSSortDescriptor *sortByPoints = [[NSSortDescriptor alloc] initWithKey:#"points" ascending:NO];
// Put them in an array
NSArray *sortDescriptor = [[NSArray alloc] initWithObjects:sortByPoints, nil];
// Pass the array to the fetch request
[fetchRequest setSortDescriptors:sortDescriptor];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"Problem %#", error);
}
for (Score *s in fetchedObjects) {
NSLog(#" %# %d",s.playerName, [s.points integerValue]);
}
}
This is how I call it in the final scene/class
AppDelegate *appDelegateReference = [[AppDelegate alloc] init];
[appDelegateReference fetchObject];
Hope this will work, after fetching your Score entity , simply assign new values in it don't use insert object for update any value.
[scoreEntity setPoints:[NSNumber numberWithInteger: spaceshipSceneReference.score]];
[scoreEntity setPlayerName:#"Joe"];
then Save the values:
NSError *error = nil;
// Saves the managedObjectContext
if (! [[self managedObjectContext] save:&error] ) {
NSLog(#"An error! %#", error);
}

How to make a conditional request with NSManagedObjectContext?

I'm new to NSManagedObjectContext. I have created an entity Link in my app, which contains a NSString *url.
At some point of my app, I need to insert a new Link in my base, so I simply do this :
Link *link = [NSEntityDescription
insertNewObjectForEntityForName:#"Link"
inManagedObjectContext:self.managedObjectContext];
link.url = myUrl;
But before doing this, I want to check if there is not already a Link in my base with the same url. And I have no idea of how to do so... what should I do?
EDIT : to retrieve data from the base I'm using this method from a tool I found on the web:
// Fetch objects with a predicate
+(NSMutableArray *)searchObjectsForEntity:(NSString*)entityName withPredicate:(NSPredicate *)predicate andSortKey:(NSString*)sortKey andSortAscending:(BOOL)sortAscending andContext:(NSManagedObjectContext *)managedObjectContext
{
// Create fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// If a predicate was specified then use it in the request
if (predicate != nil)
[request setPredicate:predicate];
// If a sort key was passed then use it in the request
if (sortKey != nil) {
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
}
// Execute the fetch request
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
// If the returned array was nil then there was an error
if (mutableFetchResults == nil)
NSLog(#"Couldn't get objects for entity %#", entityName);
// Return the results
return mutableFetchResults;
}
I would like to know how to use it.
Thanks for your help.
The method you provided just searches for a NSManagedObject that matches the attributes in the NSManagedObjectContext and if one exists, it returns it.
But, what you need to implement is called the Find-or-Create pattern, which is discussed in the Core Data programming guide. Basically, you search for an object matching specific criteria and if it exists that object is returned. If that object does not exist you create it.
Core Data Programming Guide
E.g.
+ (NSString *)entityName
{
return NSStringFromClass([Link class]);
}
+ (instancetype)findUsingPredicate:(NSPredicate *)predicate withContext:(NSManagedObjectContext *)context
{
Link * entity;
// Setup the fetchRequest
NSFetchRequest * fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[[self class] entityName]];
fetchRequest.predicate = predicate;
// Credit: #Martin R
[fetchRequest setFetchLimit:1];
// Execute the fetchRequest
NSError *error = nil;
NSArray * matchingLinks = [context executeFetchRequest:fetchRequest error:&error];
// MatchingLinks will only return nil if an error has occurred otherwise it will return 0
if (!matchingLinks)
{
// handle error
// Core data returns nil if an error occured
NSLog(#"%s %#", __PRETTY_FUNCTION__, [error description]);
}
else if ([matchingLinks count] <= 0)
{
// if the count <= 0, there were no matches
NSLog(#"%s Not found", __PRETTY_FUNCTION__);
} else {
// A link with a url that matches the url in the dictionary was found.
NSLog(#"%s Found", __PRETTY_FUNCTION__);
entity = [matchingLinks lastObject];
}
return entity;
}
+ (instancetype)findUsingPredicate:(NSPredicate *)predicate orCreateWithContext:(NSManagedObjectContext *)context
{
Link * entity = [[self class] findUsingPredicate:predicate withContext:context];
if (!entity) {
entity = [[self class] createWithContext:context];
}
return entity;
}
+ (isntancetype)createWithContext:(NSManagedObjectContext *)context
{
return [[self class] alloc] initWithContext:context];
}
- (instancetype)initWithContext:(NSManagedObjectContext *)context
{
Link * entity = [NSEntityDescription insertNewObjectForEntityForName:[[self class] entityName] inManagedObjectContext:context];
return entity;
}
USE CASE:
NSString * url = #"http://www.mylink.com";
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"url = %#", url];
Link * link = [Link findUsingPredicate:predicate orCreateWithContext:self.managedObjectContext];
link.url = url;
You can do it like this (with your method):
AppDelegate *del = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = del.managedObjectContext;
NSString *urlString = #"YOUR URL HERE";
NSMutableArray *fetchedResults = [self searchObjectsForEntity:#"Link" withPredicate:[NSPredicate predicateWithFormat:#"url == %#", urlString] andSortKey:#"url" andSortAscending:YES andContext:managedObjectContext];
BOOL exist = NO;
if(fetchedResults.count >= 1){
exist = YES;
}

Deleting object from one to many relationship in Core Data

I currently have a problem deleting an object in a to many relationship.
My app have the following relationship:
Product <<- Cart
When the user pushes a "add to cart" button in my viewcontroller, the following code is setting the relations between the product object and the cart
+ (Cart *)addProductToCartWithProduct:(Product *)product inManagedObjectContext:(NSManagedObjectContext *)context {
Cart *cart = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Cart"];
NSError *error = nil;
NSArray *carts = [context executeFetchRequest:request error:&error];
if (!carts || ([carts count] > 1)) {
// handle error
} else if (![carts count]) {
cart = [NSEntityDescription insertNewObjectForEntityForName:#"Cart" inManagedObjectContext:context];
} else { // they already have a cart started
cart = [carts lastObject];
}
/*Get Object ID to safely pass NSMangedObject between threads (A background worker thread and the main thread). */
NSManagedObjectID *retID = [product objectID];
[cart addProductsObject:(Product *)[context objectWithID:retID]];
//Inverse relationship
[(Product *) [context objectWithID:retID] setInCart:cart];
return cart;
}
This then returns a cart object, which I pass to my cart viewcontroller, and fetch the products in that relationship like so:
// Fetch request for "Product":
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Product"];
// Fetch only products for the cart:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"inCart = %#", self.cart];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"navn" ascending:YES];
[fetchRequest setSortDescriptors:#[sortDescriptor]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_theManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
When I then try to delete an object from the relationship like so:
-(void)RemoveFromCart:(UIButton *)sender {
NSIndexPath *ip = [NSIndexPath indexPathForRow:sender.tag inSection:0];
Product *prod = (Product *)[self.fetchedResultsController objectAtIndexPath:ip];
prod.inCart = nil;
[_cart removeProductsObject:prod];
NSLog(#"Cart %# %#", _cart.products, prod);
[self saveCurrentContext:_theManagedObjectContext];
[self loadCart];
[_orderTable reloadData];
}
The product is removed visually (gone from the tableview/screen) because inCart is set to nil, but not technically... when I log the cart object, the product object is still in the relationship, so it seems like the [_cart removeProductsObject:prod]; is not working.
And it also doesn't work the other way around, when I try to add the same product to the cart, I just have deleted (from the cart), for some reason the inverse relationship "inCart" is not set, after I have set it to "nil", when the product object is removed.
Why is this happening? and how do I fix it? :).
EDIT:
Pictures showcasing inverse relationships in Core data model editor:
Pass Cart to other viewcontroller:
[[[DataManager sharedInstance] backgroundManagedObjectContext] performBlock:^{
UITabBarController *tabBarController = self.tabBarController;
for (UINavigationController *navController in tabBarController.viewControllers) {
for (UIViewController *vc in navController.viewControllers) {
if ([vc isMemberOfClass:NSClassFromString(#"CartViewController")]){
CartViewController *cartVC = (CartViewController *) vc;
cartVC.cart = [Cart addProductToCartWithProduct:prod inManagedObjectContext: [[DataManager sharedInstance] backgroundManagedObjectContext]];
[[DataManager sharedInstance] saveBackgroundContext];
[[DataManager sharedInstance] saveMasterContext];
NSLog(#" %#", cartVC.cart);
}
}
}
}];
Save Context
-(void)saveCurrentContext:(NSManagedObjectContext *)context {
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"NOT SAVED");
}
[[DataManager sharedInstance] saveBackgroundContext];
[[DataManager sharedInstance] saveMasterContext];
}
Okay, so I found a work around for this very weird problem.
Since the autogenerated accessor methods didn't work for some reason, I had to think of another way to delete the object from the relationship.
for (Product *prod in _cart.products) {
//To Very reliable to check for item by name attribute, but It works :)
if ([prod.name isEqualToString:product.name]) {
product = prod;
NSMutableSet *set = [NSMutableSet setWithSet:_cart.products];
[set removeObject:prod];
_cart.products = set;
}
}

iOS - How to create a login process using keychain / Core Data?

I am creating a multi-user iPhone app, and I am trying to finish up the coding for the user login in process. I can successfully create an account, and store the data the user inputs into the Core Data DB, and the pin (password) into the Keychain, so now I am trying to complete the login process. The following code listed below is what I have so far, and I am wondering what I need to do to complete the login process.
- (IBAction)processLogin:(id)sender {
// hide keyboard
[_textFieldUsername resignFirstResponder];
[_textFieldPin resignFirstResponder];
// First - make activity indicator visible, then start animating, then turn of wrong user / pin label
_welcomeActivityIndicator.hidden = FALSE;
[_welcomeActivityIndicator startAnimating];
[_wrongUserPin setHidden:YES];
// check if username and pin text fields are populated
if ([_textFieldUsername.text length ] == 0 && [_textFieldPin.text length ] == 0)
{
[_welcomeActivityIndicator stopAnimating];
[_wrongUserPin setHidden:NO];
}
// CORE DATA
NSFetchRequest *request= [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Account" inManagedObjectContext:_managedObjectContext];
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"username=%#",self.textFieldUsername.text];
//check pin
Account *pinAccount = [[Account alloc] init];
[pinAccount.password isEqualToString:_textFieldPin.text];
[request setEntity:entity];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [_managedObjectContext executeFetchRequest:request error:&error];
if (array != nil) {
NSUInteger count = [array count]; // may be 0 if the object has been deleted.
NSLog(#"Username may exist, %#",count);
}
else {
NSLog(#"Username does not exist.");
}
// TODO - put this in proper place - play audio bell if user logs in correctly
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"Glass", CFSTR("aiff"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
// TODO - put this in proper place - Load ViewControllerHome
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewControllerHome *home = (ViewControllerHome *)[storyboard instantiateViewControllerWithIdentifier:#"Home"];
[self presentModalViewController:home animated:YES];
}
The Account and AccountBase class files m and h look like the following:
Account.h http://pastie.org/4149299
Account.m http://pastie.org/4149296
AccountBase.h http://pastie.org/4149301
AccountBase.m http://pastie.org/4149302
I would appreciate any ideas or thoughts, and thanks for reading.
I was able to complete the login process with the following code.
- (IBAction)processLogin:(id)sender {
// hide keyboard
[_textFieldUsername resignFirstResponder];
[_textFieldPin resignFirstResponder];
// First - make activity indicator visible, then start animating, then turn of wrong user / pin label
_welcomeActivityIndicator.hidden = FALSE;
[_welcomeActivityIndicator startAnimating];
[_wrongUserPin setHidden:YES];
// check if username and pin text fields are populated
if ([_textFieldUsername.text length ] == 0 && [_textFieldPin.text length ] == 0)
{
[_welcomeActivityIndicator stopAnimating];
[_wrongUserPin setHidden:NO];
}
// CORE DATA
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Account" inManagedObjectContext:_managedObjectContext];
// set entity for request
[request setEntity:entity];
// filter results using a predicate
NSPredicate *pred =[NSPredicate predicateWithFormat:(#"username = %#"), _textFieldUsername.text];
// set predicate for the request
[request setPredicate:pred];
NSError *error = nil;
// store DB usernames in results array
NSArray *results = [_managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"The returned results are %#",results);
// check text field against results stored in DB
for (Account *anAccount in results) {
if ([anAccount.username isEqualToString:_textFieldUsername.text]){
NSLog(#"Your username exists");
if ([anAccount.password isEqualToString:_textFieldPin.text]){
NSLog(#"Your pin is correct");
// TODO - put this in proper place - play audio bell if user logs in correctly
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"Glass", CFSTR("aiff"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
// TODO - put this in proper place - Load ViewController(Root)Home
if([anAccount.username isEqualToString:#"root"])
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewControllerRootHome *roothome = (ViewControllerRootHome *)[storyboard instantiateViewControllerWithIdentifier:#"rootHome"];
[self presentModalViewController:roothome animated:YES];
}
else {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewControllerHome *home = (ViewControllerHome *)[storyboard instantiateViewControllerWithIdentifier:#"Home"];
[self presentModalViewController:home animated:YES];
}
}
else {
NSLog(#"Your pin is wrong");
[_welcomeActivityIndicator stopAnimating];
[_wrongUserPin setHidden:NO];
}
}
else {
NSLog(#"Your username was not found");
[_welcomeActivityIndicator stopAnimating];
[_wrongUserPin setHidden:NO];
}
}
}
I believe your mis-using core data. It is not meant to be used like sqlite, always running always query-able. (http://cocoawithlove.com/2010/02/differences-between-core-data-and.html)
You are trying to keep a database of user but your also over complicating it. While in memory the app can use an NSMutableArray of your own objects to keep track of usernames, tabs
So you would have your class:
interface Alcoholic : NSObject
#property(nonatomic,retain)NSString * username;
#property(nonatomic,retain)NSString * pin;
#property(nonatomic,retain)NSString * tab;
#end
In the section of code that adds these it would have a mutable array
NSMutableArray * alcoholics = [[NSMutableArray alloc]init];
- (IBAction)processLogin:(id)sender {
int i = 0;
while (i<alcoholics.count)
{
Aloholic = [alcoholics objectAtIndex:i];
if(self.textFieldUsername.text == Aloholic.username)
NSLog(#"Username may exist, %#",count);
}
else {
NSLog(#"Username does not exist.");
}
}
etc...
Since Im sure your next question is how to make it persistent and thats where core data comes into play.
in your app delegate get the alcoholics array and save that to core data when the app opens and closes
-(void)save
{
//use core data to save needed data persitently
self.Values = [NSEntityDescription
insertNewObjectForEntityForName:#"processLoginClass"
inManagedObjectContext:[self managedObjectContext]];
self.Values.alcoholics = self.processLoginClass.alcoholics;
}
NSError *error;
if (![[self managedObjectContext] save:&error])
{
NSLog(#"Couldn't save state information: %#", [error localizedDescription]);
}
}
-(void)load
{
//use core data to load needed data
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Values"
inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
for (processLoginClass *info in fetchedObjects)
{
[self.processLoginClass setAlcholics:info.alcholics];
}
}

Resources