This question already has answers here:
how to cancel out of operation created with addOperationWithBlock?
(2 answers)
Closed 8 years ago.
So, I am using the addOperationWithBlock^{}method of the NSOperationQueue and I want to put the fine grained isCancelled property check at points in the operation code. How do I get the instance of the operation that will run while in this block?
For example, this is my code snippet:
[operationQueueInstance addOperationWithBlock:^{
if (!???.isCancelled){
NSlog(#"Instruction 1");
}
if (!???.isCancelled){
NSlog(#"Instruction 2");
}
NSlog(#"Instruction 3");
}];
How do I get the instance of the operation this block would run in so that I can evaluate the isCancelled property for the instructions?
TIA
From the Apple docs:
You should not attempt to get a reference to the newly created
operation object or divine its type information.
You could instantiate a NSBlockOperation and assign it to a variable to keep an explicit reference instead.
addOperationWithBlock seems to be a shortcut for whenever you don't need a reference to the operation object.
Make sure to mark your block operation with the __block storage qualifier to avoid retain cycles.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Weak and strong property setter attributes in Objective-C
I am new to iphone development . Can any one tell me when to use strong and when to use weak reference and also what is the difference between atomic and nonatomic. I went through many links but still I am not clear with it.
I also wanted to know the differnce between retain,copy and assign used prior to ios5.
Any help is appreciated..
Thanks,
Raj
When designing your data you need to understand the concept of ownership. Data owns downwards. Ownership can never go back up your data hierarchy. If A has a pointer to B, and B to C, then C owns A, you have a cyclic reference graph, which results in a memory leak due to A referencing C indirectly and C referencing A. Release A and it doesn't get deleted because C still has a reference, and it won't get deleted unless A does - a catch 22.
To avoid scenarios like this, you use strong pointers to point "down" your data, and use weak pointers for any back references (such as parent pointers for example).
If a property is atomic, it generates a setter that allows it to be set from multiple threads. You cannot have race conditions where one thread changes a property at the same time as another. Nonatomic properties don't have that thread locking system.
Finally, retain properties increase the reference count of an object when you assign them to it by calling [myObject retain] on the object. Copy calls [myObject copy] so the property does not refer to the original, but a copy and assign is just a straight assignment with no reference count adjustment.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between releasing and autoreleasing?
Hi can you please elaborate what is the difference between release and auto release and is there any way to create a user defined autorelease pool?and the real use of auto release pool.
Release reduces the object's reference count immediately, which means that if its retain count reaches zero it'll be immediately deallocated. Autorelease is a delayed release -- it's useful for ownership handoffs.
Consider a method like +[NSString stringWithFormat:]. It creates a new NSString instance (with alloc & some form of init) and then hands it off to the caller. That class method doesn't want to still "own" the created string after that, but if it releases the new string before returning, the new string will get deallocated before the caller gets it. Instead, it autoreleases the new string: that means the string will stick around long enough for the caller to grab it and retain it if needed.
What happens if the caller doesn't retain it? That's where autorelease pools come into play. The NSAutoreleasPool keeps track of every autorelease, and when told to drain, it releases all the objects in its pool (causing them to get deallocated if their reference count goes to zero). By default in a Mac or iOS app, there's an autorelease pool in the main event loop -- so if you call stringWithFormat: and don't retain the result, it'll go away on the next pass.
You can create your own autorelease pool with NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] and drain it with [pool drain]. This can be useful if you have a section of code where you're creating a lot of temporary objects.
release releases the object immediately while autorelease does it some time in the future.
Example: You'd want to return an autoreleased object here, because if you'd release it, it would already get dealloc before the code calling this method can make use of the returned object!
- (NSObject *)someMethod
{
return [[[NSObject alloc] init] autorelease];
}
I am trying to create an NSOperation by subclassing from NSOperation.I want my operation to be executed on a separate thread as well as it should support canceling option i.e i should be able to stop the thread(or the operation) at any point of time.I tried adding my operation instance to NSOperationQueue,everything is working fine but "the operation" is being executed after some time which makes my application slow.So i tried running my operation alone by calling [theOperation start]; its pretty fast but executing on the main thread.How to make the NSOperation run on separate thread with canceling option please help.
either:
1) do not make it an NSOperation and explicitly create a thread.
2) use a second operation queue and/or increase the priority.
3) use a container type for the result. when you need it immediately, cancel the background load operation and load manually.
I believe you need to implement - (BOOL)isConcurrent:
- (BOOL)isConcurrent
{
return YES;
}
But there are implications. Read the Apple reference docs on NSOperation, particularly the section Subclassing Notes. Also note that if you want the operation to be cancellable, you need to implement the cancelling behaviour yourself: eg, in your main selector you need to check if the operation has been cancelled, and immediately return if it has.
I am trying to perform a selector which returns an NSString in the background thread, and the NSString returned will depend on the input object albumlink.
I am performing it in the background, as it takes a while to shorten the URL.
I would really appreciate if you could tell me how I could get the return string.
My code to perform that selector is:
[self performSelectorInBackground:#selector(shortenURL:) withObject:albumlink];
You can write another method in your class (let's call it -handleResponse:(NSString *)response), and then from the backgrounded process you can call:
[self performSelectorOnMainThread:#selector(handleResponse:) withObject:#"My response string" waitUntilDone:NO];
You can't get a function's return value outside of the thread it runs in. The whole point of doing something in a background thread is that it's taken out of the normal flow for the main thread, so there's no place for it to return to.. The most sensible approach is to create a block that's performed in the background (either through NSOperation or GCD directly) which updates either updates the value on the main thread — if you need to store the value afterward — or which just does whatever you were going to do with the value if it was only going to be used in one branch of code.
This question already has answers here:
Check whether or not the current thread is the main thread
(13 answers)
Closed 9 years ago.
My code needs to guarantee a certain operation run on the main thread, but calls may come from background threads.
To detect situations in the background I was using the following:
- (void)selectorToRunInMainThread:(id)arguments
{
// push to main thread
if ([NSRunLoop currentRunLoop] != [NSRunLoop mainRunLoop])
{
[self performSelectorOnMainThread:#selector(selectorToRunInMainThread:) withObject:arguments waitUntilDone:NO];
return;
}
/*
... function content ...
*/
}
This works on iOS 4 and iOS 3.2 but not on iOS 3.1.3 and earlier. In these earlier versions, the function will keep getting called in an endless loop.
Changing the comparison to:
if (![[NSRunLoop currentRunLoop] isEqualTo:[NSRunLoop mainRunLoop]])
has no effect, they still never compare to the same value.
I found a solution that appears to be working, but I'd like to see what other people suggest first.
[NSThread isMainThread] and, if not, dispatch via any of a number of mechanisms to the main thread (what you have is fine).