1

In a class I have @property BOOL clearCookies;

I'd like to set it up so that I can do some additional things when the item is set.

In my code I could do something like classInstance.clearCookies = YES;

Then in the setter method something like this java example from android:

public void setClearCookies(boolean clearCookies) {
        _instance.clearCookies = clearCookies;
        _instance.doOtherThings();
    }

What's the best way to achieve that in Objective C? Basically I want to set the boolean property but then also do some other things (actually clearing the cookies from my UIWebView)

Tom Hammond
  • 5,842
  • 12
  • 52
  • 95

3 Answers3

2

You can do like this:

-(void)setClearCookies:(BOOL)clearCookies {
        _clearCookies = clearCookies;
       [self doOtherThings];
    }
sanjana
  • 3,034
  • 2
  • 25
  • 31
2
-(void)setClearCookies:(BOOL)clearCookies
{
    @synchronized(self)
    {
       _clearCookies = clearCookies;
       [self doOtherThings];
   } 
}

- (BOOL)clearCookies
{
   @synchronized (self)
   {
       return _clearCookies;
   }
}
Andrey Chernukha
  • 21,488
  • 17
  • 97
  • 161
  • Looks perfect! Thanks for the speedy response! – Tom Hammond Apr 04 '17 at 14:42
  • Looks like it doesn't like have a synthesized getter: `writable atomic property cannot pair a synthesized getter with a user defined setter`. Would you mind providing an example of how to write a getter for this as well? :) – Tom Hammond Apr 04 '17 at 14:52
  • It would be better to make the property nonatomic rather than leave it as atomic but implement the getter/setter in nonatomic ways. – dan Apr 04 '17 at 14:57
  • @TomHammond I updated my answer. This code will keep the setter and the getter atomic – Andrey Chernukha Apr 04 '17 at 15:02
1

Another way to avoid thread conflicts (alternative to @synchronized()), is using Grand Central Dispatch (which in the majority of cases is faster than the former):

@property (assign, nonatomic) BOOL clearCookies;

// Later in code
static dispatch_queue_t clearCookiesQueue;

- (void)setClearCookies:(BOOL)clearCookies {
    [self initializeClearCookiesQueue];

    dispatch_async(clearCookiesQueue, ^{ // Note, this is "async"
        _clearCookies = clearCookies;
    });
}


- (BOOL)clearCookies {
    [self initializeClearCookiesQueue];

    __block BOOL clearCookies;
    dispatch_sync(clearCookiesQueue, ^{ // Note, this is "sync"
        clearCookies = _clearCookies;
    });

    // As "sync" waits until the operation is finished, you can define
    // your other operations here safely.
    [self doOtherStuff];

    return clearCookies;
}


/**
    Checks if the queue for the clearCookies property is initialized and,
    if it's not, initializes it.
*/
- (void)initializeClearCookiesQueue {
    if ( ! clearCookiesQueue ) {
        // We'll use a serial queue to avoid conflicts reading/writing the ivar
        clearCookiesQueue = dispatch_queue_create("com.yourapp.yourviewcontroller.someUniqueIdentifier", DISPATCH_QUEUE_SERIAL); // Note, this is a C string, not NSString
    }
}

If you don't care about threading, or you don't need it, just overriding your setter is enough:

- (void)setClearCookies:(BOOL)clearCookies {
    _clearCookies = clearCookies;
    [self doOtherStuff];
}
Community
  • 1
  • 1
Alejandro Iván
  • 3,969
  • 1
  • 21
  • 30