I have a class with a property
#property (nonatomic) double* myDoubles
This property has 3 doubles in it
myDoubles[0]; //0.02
myDoubles[1]; //0.42
myDoubles[2]; //0.99
If the values change, I'd like the following method to be called
[self setNeedsDisplay];
I tried using FBKVOController, but that didn't work..
_observer = [FBKVOController controllerWithObserver:self];
[_observer observe:self
keyPath:#"myDoubles"
options:NSKeyValueObservingOptionNew
action:#selector(setNeedsDisplay)];
I don't want to start an NSTimer and just check for changes.
This is not possible.
Notifications work because the code making changes does so through some method that knows to notify listeners of the change. If that same code were simply to write to the memory location backing the data, the notification would never be triggered.
What you want to do is simply declare a memory location that code will write to; no notification can happen from this (unless you have very system-dependent support making it possible - a memory watchpoint - and then your question changes significantly. Such support, when available, is very limited and not of good generic value).
Related
Apple provides some documentation about synchronizing variables and even order of execution. What I don't see is any documentation on CPU cache behavior. What guarantees and control does the Objective-C developer have to ensure cache coherence between threads?
Consider the following where a variable is set on a background thread but read on the main thread:
self.count = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
self.count = 5;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%i", self.count);
});
}
Should count be volatile in this case?
Update 1
The documentation in Inter-thread Communication guarantees that shared variables can be used for inter-thread communication.
Another simple way to communicate information between two threads is to use a global variable, shared object, or shared block of memory.
Does this imply volatile is not required in this case? This is conflicting with the documentation in Memory Barriers and Volatile Variables:
If the variable is visible from another thread however, such an optimization might prevent the other thread from noticing any changes to it. Applying the volatile keyword to a variable forces the compiler to load that variable from memory each time it is used.
So I still don't know whether volatile is required because the compiler could use register caching optimizations or if it's not required because the compiler somehow knows it's a "shared" something.
The documentation is not very clear about what a shared variable is or how the compiler knows about it. In the above example, is count a shared object? Let's say count is an int, then it's not an object. Is it a shared block of memory or does that only apply to __block declared variables? Maybe volatile is required for non-block, non-object, non-global, shared variables.
Update 2
To everyone thinking this is a question about synchronization, it's not. This is about CPU cache behavior on the iOS platform.
I know you are probably asking about the general case of using variables across threads (in which case the rules about using volatile and locks are the same for ObjC as it is for normal C). However, for the example code you posted the rules are a little different. (I'll be skipping over and simplifying things and using Xcode to mean both Xcode and the compiler)
self.count = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
self.count = 5;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%i", self.count);
});
}
I'm going to assume self is an NSObject subclass something like this:
#interface MyClass : NSObject {
NSInteger something;
}
#property (nonatomic, assign) NSInteger count;
#end
Objective C is a superset of C, and if you've ever done any reverse engineering of ObjC you'll know that ObjC code (sort of, not quite) gets converted into C code before it's compiled. All [self method:object] calls get converted to objc_msgSend(self, "method:", object) calls and self is a C struct with ivars and other runtime info in it.
This means this code doesn't do quite what you might expect.
-(void)doThing{
NSInteger results = something + self.count;
}
Just accessing something isn't just accessing the variable but is instead doing self->something (which is why you need to get a weak reference to self when accessing an ivar in an Objective C block to avoid a retain cycle).
The second point is Objective C properties don't really exist. self.count gets turned into [self count] and self.count = 5 gets turned into [self setCount:5]. Objective C properties are just syntax sugar; convenience save you some typing and make things look a bit nicer.
If you've been using Objective C for more than a few years ago you'll remember when you had to add #synthesize propertyName = _ivarName to the #implementation for ObjC properties you declared in the header. (now Xcode does it automatically for you)
#synthesize was a trigger for Xcode to generate the setter and getter methods for you. (if you hadn't written #synthesize Xcode expected you to write the setter and getter yourself)
// Auto generated code you never see unless you reverse engineer the compiled binary
-(void)setCount:(NSInteger)count{
_count = count;
}
-(NSInteger)count{
return _count;
}
If you are worried about threading issues with self.count you are worried about 2 threads calling these methods at once (not directly accessing the same variable at once, as self.count is actually a method call not a variable).
The property definition in the header changes what code is generated (unless you implement the setter yourself).
#property (nonatomic, retain)
[_count release];
[count retain];
_count = count;
#property (nonatomic, copy)
[_count release];
_count = [count copy];
#property (nonatomic, assign)
_count = count;
TLDR
If you care about threading and want to make sure you don't read the value half way through a write happening on another thread then change nonatomic to atomic (or get rid of nonatomic as atomic is the default). Which will result in code generated something like this.
#property (atomic, assign) NSInteger count;
// setter
#synchronized(self) {
_count = count;
}
This won't guarantee your code is thread safe, but (as long as you only access the property view it's setter and getter) should mean you avoid the possibility of reading the value during a write on another thread. More info about atomic and nonatmoic in the answers to this question.
The simplest way, and the way that is least challenging to the developer's brain, is to perform tasks on a serial dispatch queue. A serial dispatch queue, like the main queue, is a tiny single threaded island in a multi-threaded world.
You should use lock or some other synchronise mechanism to protect the shared variable. According to the documentation it said:
Another simple way to communicate information between two threads is to use a global variable, shared object, or shared block of memory. Although shared variables are fast and simple, they are also more fragile than direct messaging. Shared variables must be carefully protected with locks or other synchronization mechanisms to ensure the correctness of your code. Failure to do so could lead to race conditions, corrupted data, or crashes.
In fact the best way to protect the counter variable is to use the Atomic Operation. You can read the article: https://www.mikeash.com/pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html
In which iOS version, atomic/nonatomic were added? iOS 2.0 , 4.0 etc
It's not an iOS SDK version feature. It's the Objective-C compiler's (LLVM by default) language feature.
#property (nonatomic) NSString* prop;
gets translated to machine code that's executed by iOS. One day somebody taught the compiler (in XCode) : if you see nonatomic keyword produc machine code equal to this operation:
- (void) setProp:(NSString *)prop_ {
[prop retain];
[prop release];
prop = userName_;
}
if you see atomic keyword make sure the access is synchronized:
- (void) setProp:(NSString*)prop_ {
#synchronized(self) {
[prop release];
prop = [prop_ retain];
} }
After it gets compiled every iOS version will understand it.
The last two are identical; "atomic" is the default behavior (note that it is not actually a keyword; it is specified only by the absence of nonatomic).
Assuming that you are #synthesizing the method implementations, atomic vs. non-atomic changes the generated code. If you are writing your own setter/getters, atomic/nonatomic/retain/assign/copy are merely advisory.
With "atomic", the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than "atomic".
I read somewhere that if i have delegates in my app, i should keep a weak reference to them
however, when i debug the app, the app doesnt want to move on, when i call on a delegate
because my delegate has already been deallocated by the time it reached that method
why ?
If i put the reference to be "strong" everything works just fine, though i am not sure what are the consequences of that on my memory allocations and the fact that those delegates are not in "sharedInstance" classes....
code:
#interface LoginProcessListener()
#property (nonatomic,weak)id<UserSettingsDelegate>userSettings;
#property (nonatomic,weak)id<DisclaimerDelegate>disclaimerDelegate;
#end
#implementation LoginProcessListener
-(instancetype)initWithUserSettings:(id<UserSettingsDelegate>)userSettings andDisclaimerDelegate:(id<DisclaimerDelegate>)disclaimerDelegate{
self = [super init];
if (self){
[self setUserSettings:userSettings];
[self setDisclaimerDelegate:disclaimerDelegate];
}
return self;
}
-(void)onLoginAuthenticationProcessFinished{
User *user = [_userSettings getUserDetails];
if(user && [_disclaimerDelegate isConfirmedDisclaimer:[user disclaimerInfo]]){
[_disclaimerDelegate confirmedDisclaimer];
}else {
[_disclaimerDelegate needDisplayDisclaimer];
}
}
-(void)onLoggedInUserDetailsReceived:(User *)user{
[_userSettings saveUserDetails:user]; <== here my _userSettings is already nil;
}
when i debug the app, the app doesnt want to move on, when i call on a delegate because my delegate has already been deallocated by the time it reached that method
But that is your bug, which you must track down. The whole point of a delegate is that you must not permit it to die before the thing whose delegate it is. In general, if a delegate dies before the other thing does, you are doing something wrong; it is the job of a delegate to live as long as it is needed.
On the other hand (there is always an "other hand") it may be that what you are calling a delegate is not really a delegate. It is a delegate more or less if it is an object with a primary existence of its own. If it's just a packet of values or a purely ancillary object whose only purpose is in connection with the object keeping a reference to it, then it is not a delegate and a strong reference is correct.
Yours architecture is wrong. It's should be:
#interface UserSettings
#property (nonatomic,weak)id<UserSettingsDelegate>userSettingsDelegate;
#end
#interface Disclaimer
#property (nonatomic,weak)id<DisclaimerDelegate>disclaimerDelegate;
#end
Actually yours userSettings not real delegate, it just member of LoginProcessListener, so you may use strong references.
Commonly id<UserSettingsDelegate> creates UserSettings and own reference on it. If UserSettings will own reference at id<UserSettingsDelegate, then there will be retain loop.
when i debug the app, the app doesnt want to move on, when i call on a
delegate because my delegate has already been deallocated by the time
it reached that method
What's your seeking is how a weakly defined property behaves.
Via the docs: https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html#/apple_ref/doc/uid/TP40011210-CH5-SW30)
Because a weak reference doesn’t keep an object alive, it’s possible for the referenced
object to be deallocated while the reference is still in use. To avoid a dangerous
dangling pointer to the memory originally occupied by the now deallocated object, a weak
reference is automatically set to nil when its object is deallocated.
Simply put, if the delegate is no longer allocated, it's being released elsewhere.
With that said, your bug is likely not there at all, but elsewhere. You're going to have to backtrace _userSession to verify where it's being created and what objects have strong references to it.
Using a strong reference to a delegate is permissible, but you need to understand what is going on as it has risks that you should be aware of.
Apple's documentation kind of glosses over this, just saying that delegate users keep a weak link to the delegate, and in general this is true, but there are cases, and yours may be one of them, where it makes sense to keep a strong reference. In general, this happens in asynchronous code where the delegate might otherwise be released before it is used.
Too much hand waving: here is a concrete example. NSURLConnection needs a delegate to do asynchronous IO. In order to make this reliable and to greatly simplify it's usage, NSURLConnection keeps a strong reference to it's delegate as long as it needs one. Here is a quote from the NSURLConnection documentation :-
"Note: During a request, the connection maintains a strong reference to its delegate. It releases that strong reference when the connection finishes loading, fails, or is canceled"
In simple terms, under ARC, "releases that strong reference" probably means setting the property to nil.
Summary: If you know what you're doing, use strong references when you have to, and document well so that the next person to see that code understands why you did it.
You can temoprarily make a strong reference to the delegate object, which is excatly what NSURLConnectionDelegate protocol does. I do it like this:
Let's say i have a protocol for downloading images.
#implementation AsyncImageLoadManager <NSURLConnectionDelegate>
static char delegateStrongReferenceKey;
.......
-(void)startDownload {
....
objc_setAssociatedObject(self, &delegateStrongRefernceKey, _delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
_imageConnection = [NSURLConnection connectionWithRequest:request delegate:self];
objc_setAssociatedObject(self, &delegateStrongRefernceKey, _delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
_downloadTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ //I use tihs instead of [connection start]; so that download continues if app goes to background
[_imageConnection cancel];
[[UIApplication sharedApplication] endBackgroundTask:_downloadTaskID];
_downloadTaskID = UIBackgroundTaskInvalid;
objc_setAssociatedObject(self, &delegateStrongRefernceKey, nil, OBJC_ASSOCIATION_ASSIGN);
}];
}
..../// and in connectionDidFinishLoading and connectionDidFailWithError you release the strong reference with:
[[UIApplication sharedApplication] endBackgroundTask:_downloadTaskID];
_downloadTaskID = UIBackgroundTaskInvalid;
objc_setAssociatedObject(self, &delegateStrongRefernceKey, nil, OBJC_ASSOCIATION_ASSIGN);
We created an operation framework to add some functionality not found in the base classes (e.g. tracking success/failure). Parent operations are usually non-concurrent, and may only exist to manage child operations. Child operations which are typically concurrent (downloading xml and media asynchronously).
When we run our application on iOS 7, add we a number of operations to the operation queue, ~3/4 of the operations complete, and then the app appears to hang.
When I pause the app in the debugger, and I examine the operations in the queue (sOpQueue.operations), many of them are ready to run (isReady returns TRUE), but apparently none of them are executing (isExecuting returns FALSE, and I see no evidence of any operation running on any thread).
This is a new problem as of iOS 7.
The behavior does not seem to change when I increase or decrease the number of concurrent operations.
Does anyone have any suggestions on how to determine why a ready operation is not being started?
Thanks,
Chuck
Are you issuing the isReady Key Value Observing notification?
For example, I use a property:
#property (nonatomic, getter = isReady) BOOL ready;
And then have a custom setter:
- (void)setReady:(BOOL)ready
{
[self willChangeValueForKey:#"isReady"];
_ready = ready;
[self didChangeValueForKey:#"isReady"];
}
As well as a custom getter that calls super:
- (BOOL)isReady
{
return _ready && [super isReady];
}
And, because you implemented both the setter and getter, you have to manually synthesize the property at the beginning of the #implementation (usually you don't have to do this anymore, but if you implement all of the custom accessors, you have to manually #synthesize):
#synthesize ready = _ready;
Then, the operation starts when both of the following conditions are satisfied:
The ready property is set to YES (note, use the setter, not the ivar directly);
self.ready = YES;
or
[self setReady:YES];
All other standard NSOperation criteria are satisfied (e.g. dependencies between operations, honoring maxConcurrentOperationCount, factoring in priorities, etc.).
I'll bet you have concurrent operations that haven't finished properly. Raise you number of concurrent operations and see if you can run longer before it hangs. Then figure out why your concurrent operations aren't correctly setting isFinished.
I made a class, called Timer. Its designated initializer starts a timer with a value in seconds. It works great. However I am having trouble updating the controller w/e the timer ticks.
Right now, for every tick I am sending a NSNotificationCenter with a userInfo that is a simple dictionary with the current time, which does not sound the best way to do it...
NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:self.timerCount] forKey:#"timerCount"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"TimerCountChanged"
object:self
userInfo:dict];
Should I be using some other technique or am I doing it the right way?
Thank you in advance!
EDIT:
I need to initialize different Timers, using different values. I tried to use Delegates, but I only had one method in my controller to update the UI for all those Timers!
Would it be bad if I do something like? Passing a UIButton to my Model also does not seem to be the best solution but it works.
-(void)timer:(Timer *)timer didTriggerAt:(NSTimeInterval)time andButton:(UIButton *)button
{
[button setTitle:[NSString stringWithFormat:#"%.0f", time] forState:UIControlStateNormal];
}
- (IBAction)startCountDown:(UIButton *)sender
{
self.timer1 = [[Timer alloc] initWithTimeInSeconds:10 andButton:sender];
self.timer1.delegate = self;
}
I have 3 Timers in my MainView, the user can start them whenever he wants. They can also have different times, which is also defined by the user.
Sending Notifications is good, but you may not observe it as in regular time.
Sometimes it gets delayed and you may observe them in irregular time interval.
You can use
Delegate Pattern.
Call method by selector
EDIT:
From
Apple documentation on Performance CodeSpeed on Notifications.
The fewer notifications you send, the smaller the impact on your
application’s performance. Depending on the implementation, the cost
to dispatch a single notification could be very high. For example, in
the case of Core Foundation and Cocoa notifications, the code that
posts a notification must wait until all observers finish processing
the notification. If there are numerous observers, or each performs a
significant amount of work, the delay could be significant.
If you only have one client object for each Timer instance, then you should use the delegate pattern. You would define a TimerDelegate protocol with a method that a Timer object can call whenever the timer ticks.
e.g.
#class Timer;
#protocol TimerDelegate
- (void) timer:(Timer *)timer didTriggerAt:(NSTimeInterval)time;
#end
#interface Timer
...
#property (assign) id<TimerDelegate> delegate;
...
#end
If you indeed require multiple listeners each time a Timer instance ticks, then the NSNotificationCenter approach would be a better fit. Instead of passing info in the userInfo dictionary, I probably would expose an #property on Timer called currentTime, so that when a client object gets the notification, they could simply access currentTime on the notifying Timer, instead of (IMO clunkily) reading data out of userInfo.