UA-17470720-3

Jump to content


Photo
- - - - -

Core Data Modify a Field / Property Value Before Insert / Update

data-stores core-data

  • Please log in to reply
11 replies to this topic

#1 wizgod

wizgod

    I'm what you guys call a User

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 575 posts
  • LocationThe Grid
Reputation: 149
Popular

Posted 19 April 2013 - 11:49 PM

Greetings Programs!

I have a core data project with a SiteEntity containing properties [name, url, username, password].

I need to modify the password before it saves to the store; from another post, I believe it will go in the following code but they didn't fired and I'm not sure what I need to add.

- (void)tableViewModel:(SCTableViewModel *) tableViewModel itemAddedForSectionAtIndexPath:(NSIndexPath *) indexPath item:(NSObject *) item
{
    // Get managedObjectContext from application delegate
    NSManagedObjectContext *managedObjectContext = [(iKunenaAppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];
    
    NSError *error;
    if (![managedObjectContext save:&error]) {
        NSLog(@"Error updating site: %@", [error localizedDescription]);
    }
    else {
        NSLog(@"New site added successfully.");
    }
    
}

- (void)tableViewModel:(SCTableViewModel *) tableViewModel itemEditedForSectionAtIndexPath:(NSIndexPath *) indexPath item:(NSObject *) item
{
    // Get managedObjectContext from application delegate
    NSManagedObjectContext *managedObjectContext = [(iKunenaAppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];
    
    NSError *error;
    if (![managedObjectContext save:&error]) {
        NSLog(@"Error updating site: %@", [error localizedDescription]);
    }
    else {
        NSLog(@"Site updated successfully.");
    }
    
}


Thanks!

Wg

P.S. I love Swift... talk Swift.. Never too old school to learn yet another programming language. LOL! ;-)


#2 ozie

ozie

    ¯\_(ツ)_/¯

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 526 posts
  • LocationAustralia
Reputation: 169
Popular

Posted 19 April 2013 - 11:58 PM

add self.tableViewModel.delegate = self

add to the .h file <SCTableViewModelDelegate>

Edited by ozie, 19 April 2013 - 11:58 PM.

P.S. I hate Swift.. don't talk Swift.. Too old school to learn yet another programming language.


#3 wizgod

wizgod

    I'm what you guys call a User

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 575 posts
  • LocationThe Grid
Reputation: 149
Popular

Posted 20 April 2013 - 12:01 AM

Thanks, that worked! Now I just need to figure out how to change the value :)

Like you said, Tarek must be really hard at it with 3.2 LOL.

Edited by wizgod, 20 April 2013 - 12:09 AM.

P.S. I love Swift... talk Swift.. Never too old school to learn yet another programming language. LOL! ;-)


#4 Dave Guerin

Dave Guerin

    Forum Master

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 545 posts
  • LocationIreland
Reputation: 137
Popular

Posted 20 April 2013 - 12:19 PM

Hi wizgod,

Re: "Now I just need to figure out how to change the value"

Select the Core Data Entity(s) in Xcode, then Editor > Create NSManagedObject Subclass...

That will create subclasses of your Entity(s) so you can then access your Entity objects in the same way as any other objects.

Don't edit the generated subclasses, as you will need to regenerate them whenever you change the Core Data model. If you want to do anything extra do it in a class category. For example I create folders to store files in when the Core Data entity is first created in awakeFromInsert in the category.

HTH

HTH
  • wizgod likes this
Cheers,

Dave

www.dgapps.ie

#5 wizgod

wizgod

    I'm what you guys call a User

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 575 posts
  • LocationThe Grid
Reputation: 149
Popular

Posted 20 April 2013 - 01:42 PM

Thanks Dave!

I found the generated class was what I already had created manually but mine was NSObject and it didn't import CoreData.h. I just went with the generated one to make it easier, if (like you said) I change the Core Data model later.

So I made the change to the object in the above code like this:

In the viewDidLoad:

    self.tableViewModel.cellActions.didSelect = ^(SCTableViewCell *cell, NSIndexPath *indexPath)
    {
        SCTableViewSection *section = [self.tableViewModel sectionAtIndex:indexPath.section];
        SCArrayOfObjectsSection *objectsSection = (SCArrayOfObjectsSection *)[self.tableViewModel sectionAtIndex:indexPath.section];
       
        // Get the corresponding managed object.
        NSManagedObject *object = (NSManagedObject *)[objectsSection.items objectAtIndex:indexPath.row];
       
        if(self.tableViewModel.modeledTableView.editing)
        {
            NSString *decryptedPassword = [StringEncryption DecryptString:[object valueForKey:@"password"]];
            [object setValue:decryptedPassword forKey:@"password"];

            [(SCArrayOfObjectsSection *)section dispatchEventSelectRowAtIndexPath:indexPath];
        }
        else
        {
            // Custom controller
        }
    };

And then:

- (void)tableViewModel:(SCTableViewModel *) tableViewModel itemAddedForSectionAtIndexPath:(NSIndexPath *) indexPath item:(NSObject *) item
{
    // Get managedObjectContext from application delegate
    NSManagedObjectContext *managedObjectContext = [(iKunenaAppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];
    
    NSString *encryptedPassword = [StringEncryption EncryptString:[item valueForKey:@"password"]];
    [item setValue:encryptedPassword forKey:@"password"];
    
    ...
}

- (void)tableViewModel:(SCTableViewModel *) tableViewModel itemEditedForSectionAtIndexPath:(NSIndexPath *) indexPath item:(NSObject *) item
{
    // Get managedObjectContext from application delegate
    NSManagedObjectContext *managedObjectContext = [(iKunenaAppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];

    NSString *encryptedPassword = [StringEncryption EncryptString:[item valueForKey:@"password"]];
    [item setValue:encryptedPassword forKey:@"password"];
    
    ...
}

Edited by wizgod, 20 April 2013 - 02:45 PM.

P.S. I love Swift... talk Swift.. Never too old school to learn yet another programming language. LOL! ;-)


#6 Dave Guerin

Dave Guerin

    Forum Master

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 545 posts
  • LocationIreland
Reputation: 137
Popular

Posted 22 April 2013 - 01:35 AM

Hi wizgod,


Isn't the (NSObject *) item one of your entities? As is the objectAtIndex:?

If so then you can cast the item to your entity:


YourEntity *yourEntity = (YourEntity *)item;

and then just do:

NSString *encryptedPassword = [StringEncryption EncryptString:yourEntity.password];
yourEntity.password = encryptedPassword;

Cheers,

Dave

www.dgapps.ie

#7 wizgod

wizgod

    I'm what you guys call a User

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 575 posts
  • LocationThe Grid
Reputation: 149
Popular

Posted 22 April 2013 - 08:09 PM

Hi wizgod,


Isn't the (NSObject *) item one of your entities? As is the objectAtIndex:?

If so then you can cast the item to your entity:


Hi Dave!

It saves the (NSObject *)item so that was the one I needed to set. The only two lines I needed were:

    NSString *encryptedPassword = [StringEncryption EncryptString:[item valueForKey:@"password"]];
    [item setValue:encryptedPassword forKey:@"password"];

This is the whole method; the managedObjectContext was only for the error handler. I found it in another post and figured it would come in handy for logging.

- (void)tableViewModel:(SCTableViewModel *) tableViewModel itemAddedForSectionAtIndexPath:(NSIndexPath *) indexPath item:(NSObject *) item
{
    // Get managedObjectContext from application delegate
    NSManagedObjectContext *managedObjectContext = [(iKunenaAppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];
    
    
    NSString *encryptedPassword = [StringEncryption EncryptString:[item valueForKey:@"password"]];
    [item setValue:encryptedPassword forKey:@"password"];
    
    [item setValue:@"Never" forKey:@"lastVisitedDate"];
    
    NSError *error;
    if (![managedObjectContext save:&error]) {
        NSLog(@"Error updating site: %@", [error localizedDescription]);
    }
    else {
        NSLog(@"New site added successfully.");
    }
}

Wg

P.S. I love Swift... talk Swift.. Never too old school to learn yet another programming language. LOL! ;-)


#8 ozie

ozie

    ¯\_(ツ)_/¯

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 526 posts
  • LocationAustralia
Reputation: 169
Popular

Posted 22 April 2013 - 08:18 PM

as much as [item value key:"password"] right now works, its not good practice.. if you ever change the database (now or a project in the future) and you change password to pwd... or myDate-NSString to myDate-NSDate when compiling you will get no errors, but when that line of code hits it will crash
[item value key] does not understand if key:"password" is a date or string or number so it compiles hoping you do:)

As Dave has said using the object model is best practice
myDataObject *dataobj = (myDataObject*)item;
dataobj.password = @"";

now if password was to ever be changed, be it its name, or data type, when compiling you will know if there is a problem.. either its name .password is wrong, or if its a NSNumber passing in a string will cause compiler errors

yes its a few extra lines of code, and forKey is quicker.. but not always worth it

P.S. I hate Swift.. don't talk Swift.. Too old school to learn yet another programming language.


#9 wizgod

wizgod

    I'm what you guys call a User

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 575 posts
  • LocationThe Grid
Reputation: 149
Popular

Posted 22 April 2013 - 10:01 PM

as much as [item value key:"password"] right now works, its not good practice.. if you ever change the database (now or a project in the future) and you change password to pwd... or myDate-NSString to myDate-NSDate when compiling you will get no errors, but when that line of code hits it will crash
[item value key] does not understand if key:"password" is a date or string or number so it compiles hoping you do:)

As Dave has said using the object model is best practice
myDataObject *dataobj = (myDataObject*)item;
dataobj.password = @"";

now if password was to ever be changed, be it its name, or data type, when compiling you will know if there is a problem.. either its name .password is wrong, or if its a NSNumber passing in a string will cause compiler errors

yes its a few extra lines of code, and forKey is quicker.. but not always worth it


Hi ozie!

So if I use:

myDataObject *dataobj = (myDataObject*)item;
dataobj.password = @"";

It will save "myDataObject" and not "item"? I thought it wouldn't so that's the only reason why I wasn't using the suggested method.

Wg

Edited by wizgod, 22 April 2013 - 10:03 PM.

P.S. I love Swift... talk Swift.. Never too old school to learn yet another programming language. LOL! ;-)


#10 ozie

ozie

    ¯\_(ツ)_/¯

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 526 posts
  • LocationAustralia
Reputation: 169
Popular

Posted 22 April 2013 - 10:13 PM

item and myDataObject are one in the same.. have a read up on obj-c pointers
basically a pointer is just a place in memory where the object is sitting. and so casting it to you class its still the same piece of memory.. the same object

P.S. I hate Swift.. don't talk Swift.. Too old school to learn yet another programming language.


#11 wizgod

wizgod

    I'm what you guys call a User

  • STV 5.0 Pro
  • PipPipPipPipPipPipPip
  • 575 posts
  • LocationThe Grid
Reputation: 149
Popular

Posted 22 April 2013 - 10:28 PM

Ok; I thought it was creating a separate instance of the object, good to know.

Wg

P.S. I love Swift... talk Swift.. Never too old school to learn yet another programming language. LOL! ;-)


#12 Tarek

Tarek

    Forum Admin

  • Administrators
  • 3670 posts
Reputation: 452
Popular

Posted 29 April 2013 - 08:39 AM

Hi Wg,

You might find the willCommitBoundValue cell action a much easier alternative, as it gives you the chance to modify the value right before it gets committed. Here is how you'd go about implementing that:

passwordPropertyDef.cellActions.willCommitBoundValue = ^NSObject*(SCTableViewCell *cell, NSIndexPath *indexPath, NSObject *value)
{
  NSString *password = (NSString *)value;
  NSString *newPassword = ...;

  return newPassword;
}



P.S.: guys please always use actions instead of delegates whenever possible! :) Delegates are deprecated and are only there for backwards compatibility with STV 2.0. So in your code above, you should be using the didInsertItem section action instead of the itemAddedForSectionAtIndexPath delegate.
  • cometlinear likes this





Also tagged with one or more of these keywords: data-stores, core-data

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users