core data changing a property breaks the redo

Discussion in 'Mac Programming' started by Chirone, Aug 12, 2009.

  1. Chirone macrumors 6502

    Joined:
    Mar 2, 2009
    Location:
    NZ
    #1
    I've a property called propertyOne

    it exists in the data model the class is based off..

    in the header it's declared as
    Code:
    @property (nonatomic, retain) NSString * propertyOne;
    
    in the implementation it's put in as
    Code:
    @dynamic propertyOne;
    
    in the implementation i made the set method:
    Code:
    -(void)setWords: (NSString*)newPropertyOne {
    	[self willChangeValueForKey: @"propertyOne"];
    	propertyOne = newPropertyOne;
    	[self didChangeValueForKey: @"propertyOne"];
    }
    
    so according to the documentation i should be all sweet.
    but no
    undo works fine, but as soon as i do a redo it doesn't
    Code:
    (
        <MenuItem: 0x1296a0 Use Default>,
        <MenuItem: 0x129720 Use None>,
        <MenuItem: 0x1297a0 Use All>
    )
    
    that string is the new value of propertyOne after a redo

    the best part is that the program can undo and redo perfectly if it's just undoing and redoing the awakeFromInsert.... *sarcasm*

    what have i done wrong?
     
  2. MrFusion macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #2
    There are two reasons why it doesn't work (+ a comment):
    First reason: "setWords" should be "setPropertyOne". Otherwise the compiler is still generating its own set and get functions, as you have asked it to do via "@dynamic propertyOne;".
    If you change "setWords" to "setPropertyOne", my guess is that undo and redo will work in all cases.

    Comment: you are not doing anything special with "newPropertyOne". There is no reason why you should overwrite it. The standard method, generated by the compiler, will do just fine. Of course, if you want to special things to it, you have to overwrite it. But in this case use the correct name: "setPropertyOne".

    Second reason: why is undo/redo working with "awakeFromInsert"? Because coreData automatically supports undo and redo, when you use the correct "setPropertyOne" function.
    If you want to change values in another function, or your own implementation, then you also have to tell the undoManager how to undo your operation. You changed the value, but did not register the change with the undoManager. Type in "Undo Manager" in your Xcode documentation for more information. When you know how to do undo, you get redo for free.

    That is why I think it is going wrong.
     
  3. Chirone thread starter macrumors 6502

    Joined:
    Mar 2, 2009
    Location:
    NZ
    #3
    ah woops, that was a typo for setWords. it is already setPropertyOne and it still breaks the redo even when spelt correctly

    it's true that in that example i'm not doing anything special. But in the actual code I am. however i removed the code that was special, so that only what i typed above is there in the setPropertyOne method (that was mistakenly typed as setWord) and it still broke the redo
    the redo would still not work correctly

    i was under the impression that the
    Code:
    [self willChangeValueForKey: @"propertyOne"];
    and
    Code:
    [self didChangeValueForKey: @"propertyOne"];
    took care of the undo/redo part and doing the correct stuff in the undo manager, as that's all that is needed in the utility example/tutorial provided by apple which tells you how to write the get/set methods for the properties
     
  4. MrFusion macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #4
    You are probably right about that.
     
  5. Chirone thread starter macrumors 6502

    Joined:
    Mar 2, 2009
    Location:
    NZ
    #5
    well.. that doesn't explain why it doesn't work then :(
     
  6. MrFusion macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #6
    I haven't done much with undo/redo, so this is just pure speculation.

    Do you at some point in your program use your own NSUndoManager? Maybe there is a conflict between your manager and the NSUndoManager of coredata.
     
  7. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #7
    May of may not make a difference in your case, but you're supposed to use - (void)setPrimitiveValue: (id)value forKey: (NSString *)key when overriding a Managed Object's setter. Failing that, I'd see if removing the overridden method completely helps.
     
  8. Chirone thread starter macrumors 6502

    Joined:
    Mar 2, 2009
    Location:
    NZ
    #8
    MrFusion: nah, i'm not using my own undo manager at any point, i figured the core data one would be enough

    10,000 praises to ye!

    you saved my life!!

    thanks JoshDC!! :D

    also, thanks for your input MrFusion :D
     
  9. Chirone thread starter macrumors 6502

    Joined:
    Mar 2, 2009
    Location:
    NZ
    #9
    actually, that method is never called at all..
    o_O
     
  10. MrFusion macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #10
    Maybe it is time for a more drastic step? Create a new coredata project and start adding the code from your old one that is related to the problem at hand. For every method you replace or add, you test the undo/redo functionality until you get the same problem. When you know which function is giving the problem, edit out the lines until it starts working again.

    When you reach that point, report back to us and post all the code you have and line of code is giving all the problems.
    Sometimes starting over helps (you see the problem).
     
  11. Chirone thread starter macrumors 6502

    Joined:
    Mar 2, 2009
    Location:
    NZ
    #11
    hmm... i'm pretty stuck for time... :(
    i think i'm going to have to write this thing old school without undo and saving... kind of a pain in the ass that i still can't resolve these issues... guess it'll have to wait for the next time...

    a whole lot of thinks aren't working now like bindings..

    but nonetheless... if someone tries doing this and succeeds please tell me :)
     
  12. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #12
    Sorry, I think you misunderstood me (and I can see why). What I meant was instead of the line:

    Code:
    propertyOne = newPropertyOne;
    You should use:

    Code:
    [self setPrimitiveValue:newPropertyOne forKey:@"propertyOne"];
     
  13. Chirone thread starter macrumors 6502

    Joined:
    Mar 2, 2009
    Location:
    NZ
    #13
    ah yes, that works now

    this is really WEIRD though, because i swear i tried that before... maybe i did it differently...

    thanks again for your help JoshDC, greatly appreciated!!!
     

Share This Page