I have this code:
- (NSString *)obtenerDatosUsuario
{
__block NSString *result=#"";
[self obtenerDatosUsuarioSQL:^(NSString *resultadoSQL){
result=resultadoSQL;
}];
return result;
}
And I want that the return be the content of resultadoSQL
If my guess is correct about what happens inside your method -obtenerDatosUsuarioSQL: (i.e., it performs a lengthy operation in a background thread, and gives the result to the passed block argument), then your code runs in the following order:
You call -obtenerDatosUsuario
You call -obtenerDatosUsuarioSQL:, passing a completion handler block.
Execution proceeds forward and reaches the return statement at the end of -obtenerDatosUsuario, and exits the method body. The returned variable result hasn't been set yet!
Sometime later, the SQL query completes and the block is executed. But it is too late to return the result because execution already exited the method -obtenerDatosUsuario.
There are ways to make this asynchronous method behave synchronously (e.g. semaphores), but it generally is a very, very bad idea. Most likely, obtenerDatosUsuarioSQL is asynchronous because there is a chance (even if only a small chance) that the result won't be returned immediately. Maybe it's possible that the SQL will be slow. Or maybe you'll eventually be doing queries from multiple threads, so this query might have to wait for queries in other threads to finish. Or there might be other reasons. But whatever the reason, this method was implemented as asynchronous method, and you should embrace that, rather than fight it. If you change obtenerDatosUsuario to return synchronously, you open yourself to a wide variety of possible problems.
Instead, you should just adopt asynchronous pattern in your code. For example, let's imagine that you have some code that was planning on using the result of obtenerDatosUsuario for some other purpose, e.g.:
NSString *resultadoSQL = [self obtenerDatosUsuario];
// use `resultadoSQL` here
Just change that to:
[self obtenerDatosUsuarioSQL:^(NSString *resultadoSQL){
// use `resultadoSQL` here
}];
// but not here
And, if you're using obtenerDatosUsuarioSQL in some method that you're currently trying to return the value immediately, then change that to behave asynchronously, too. For example, let's assume you had something like:
- (NSString *)someOtherMethod {
NSString *resultadoSQL = [self obtenerDatosUsuario];
// let's assume you're doing something else with `resultadoSQL` to build some other string
NSString *string = ... // some expression using `resultadoSQL`
return string;
}
Then, you'd change that to also adopt asynchronous pattern:
- (void)someOtherMethod:(void (^)(NSString *))completionHandler {
[self obtenerDatosUsuarioSQL:^(NSString *resultadoSQL){
NSString *string = ... // some expression using `resultadoSQL`
completionHandler(resultadoSQL);
}];
}
When you first encounter this, this may seem unnecessarily complicated, but asynchronous programming is so critical, such a fundamental part of Cocoa programming, that one really must gain some familiarity with these common asynchronous patterns, such as blocks. Personally, we use block syntax so much that I create code snippets in Xcode's "Code Snippet Library" for typical block patterns, which simplifies life a lot and gets you out of the world of memorizing the unintuitive block syntax.
But don't be tempted to wrap asynchronous method in another method that makes it behave synchronously. You open yourself up to many types of problems if you do that.
Related
Often find custom setter sintaxis like this:
- (void)setParentCatalog:(Catalog *)parentCatalog {
if (_parentCatalog != parentCatalog) { //???
_parentCatalog = parentCatalog;
[self refresh];
}
}
Why i should check?
if (_parentCatalog != parentCatalog)
This checks if both _parentCatalog and parentCatalog are pointing to the same memory location.
If both are same object then no need to set the objectValue.
The reason for checking if the two are equal is to avoid executing code when it's not necessary. If the method is called very often, this could have a performance benefit. Under non-ARC, your code might look more like this:
- (void)setParentCatalog:(Catalog *)parentCatalog {
if (_parentCatalog != parentCatalog) {
[_parentCatalog release];
[parentCatalog retain];
_parentCatalog = parentCatalog;
[self refresh];
}
}
So, by checking that what you received is actually a new value, you avoid those retain and release calls happening (which are still there with ARC). You've also got [self refresh] in there, which probably doesn't need to happen unless the value has actually changed.
The idea here is that if the parameter passed in to the setter is the same object already stored in the property, then there is no need to call [self refresh] again.
A refresh method often reads in data, works on it and then re-displays it in the app's views. No need to do all this work again if the data in the property haven't really changed.
It's a decision that is use case dependant. The idea behind this guard is to prevent doing unnecessary work.
If you imagine that your [self refresh] kicked off a very expensive operation then you would be reluctant to do it every time. So if you only do it when the object actually changes you save yourself some work.
Of course this may well be the behaviour you are looking for in which case you would need to stick the [self refresh] call outside of the guard.
Like all code examples you find it's worth weighing up the trade offs of the implementation and then you can better decide what you need in your case.
So, I'm attempting to have a method that effectively does this:
- (void)doWhile: (/*some magical type*/)condition
{
while (condition)
{
// do some magical things
}
}
And while your first suggestion might be a BOOL consider the following exceptions:
[someObject doWhile: someOtherObject];
// yes, I know that I could just do (someOtherObject != nil), but
// I should be able to just use (someOtherObject), right?
// seeing as how ifs/fors/whiles can use just the object.
[someObject doWhile: [someOtherObject isValid]];
// since -isValid returns a BOOL, this will work, but it will only
// pass the value of -isValid at the time of calling to the while loop.
// if the value of -isValid changes, -doWhile: will have no idea of the change,
// whereas while() would.
The use of the primitive _Bool allows me to solve the former problem, however the latter problem still persists. Is there some way to evaluate the truthfulness of a type-agnostic parameter identically to how while() works?
As noted in comments, passing a block is a versatile way of getting the desired result even though simpler methods may be appropriate for the test cases where a completely dynamic evaluation isn't required.
Is there an equivalent to [NSOperationQueue currentQueue] or [NSThread currentThread] for NSOperation?
I have a fairly complex domain model where the heavy processing happens quite deep down in the call stack. In order to timely cancel an operation I would need to pass the NSOperation as a parameter to every method until I get to the point where I want to interrupt a longer running loop. Using threads I could use [[NSThread currentThread] isCancelled] so it would seem convenient if there is an equivalent for NSOperation, unfortunately there is only the seemingly useless [NSOperationQueue currentQueue].
Came up with an extension in swift that returns the running operations
extension NSOperationQueue {
public var runningOperations: [NSOperation] {
return operations.filter {$0.executing && !$0.finished && !$0.cancelled}
}
}
You can then pick up the first one
if let operation = aQueue.runningOperations.first {}
No, there's no method to find the currently executing operation.
Two ways to solve your problem:
Operations are objects. If you need object A to talk to object B, you'll need to arrange for A to have a reference to B. There are lots of ways to do that. One way is to pass the operation along to each object that needs to know about it. Another is to use delegation. A third is to make the operation part of some larger "context" that's passed along to each method or function. If you find that you need to pass a reference from one object through several others just to get it to the object that will finally use it, that's a clue that you should think about rearranging your code.
Have the "heavy lifting" method return some value that gets passed up the call chain. You don't necessarily need the heavy lifting method to call [currentOperation cancel] to accomplish your goal. In fact, it would be better to have it return some value that the operation will understand to mean "work is done, stop now" because it can check that return value and exit immediately rather than having to call -isCancelled once in a while to find out whether it has been cancelled.
This isn't a good idea. Operations are usually canceled by their queue. Within the operation's main() method, you can periodically check if self is cancelled (say, every n trips through a loop, or at the start of every major block of commands) and abort if so.
To respond to a cancellation (say, some UI element tied to the operation's or queue's status), you use key value observing (KVO) to have your controller observe the operations' started, completion, and cancelled properties (as needed), then set your UI's state (always on the main thread) when those keys are updated. Per JeremyP's comments, it's important to note the KVO notifications come from the op's thread and UI should (almost) always be manipulated on the main thread, so you'll need to use -performSelectorOnMainThread... methods to update your actual UI when you receive a state change KVO note about your operations.
What are you really trying to do? That is, why do you feel other parts of your app need to know directly about the current operation?
You could store the current operation in the thread dictionary. Just remember to get rid of it before you exit. You can safely use the thread dict if you created the object.
You can use a combination of [NSOperationQueue currentQueue] & [NSThread currentThread] to accomplish this.
Essentially, you need to loop through the operations on the currentQueue and find the operation running on the currentThread.
NSOperation doesn't provide access to the thread it is running on, so you need to add that property yourself and assign it.
You're probably already subclassing NSOperation and providing a main, so add a 'thread' property to that subclass:
#interface MyOperation : NSOperation
#property(nonatomic,strong) NSThread *thread ;
#end
Then, in your 'main' assign the current thread to that property
myOperation.thread = [NSThread currentThread]
You can then add a 'currentOperation' method:
+(MyOperation *)currentOperation
{
NSOperationQueue *opQueue = [NSOperationQueue currentQueue] ;
NSThread *currentThread = [NSThread currentThread] ;
for( MyOperation *op in opQueue.operations ) {
if( [op isExecuting] && [op respondsToSelector:#selector(thread)] ) {
if( op.thread == currentThread ) {
return ( op ) ;
}
}
}
}
return nil ;
}
How do you know which operation you want to cancel?
When you get to the point that you want to cancel, just call [myQueue operations] and go through the operations until you find ones that you now want to cancel. I guess if you have millions of operations (or thousands) this might not work.
[myQueue operations] is thread safe - a snapshot of the Queue contents. You can dive through it pretty quick cancelling at will.
Another way:
NSOperationQueue is not a singleton, so you can create a Q that has say 200 jobs on it, and then cancel all 20 by just getting that Q and cancelling them all. Store the Q's in a dictionary on the main thread, and then you can get the jobs you want canceled from the dict and cancel them all. i.e. you have 1000 kinds of operations and at the point in the code where you realize you don't need a certain task, you just get the Q for that kind, and look through it for jobs to cancel.
Blocks are awesome. Because I thought I understood them, I wanted to up the ante and use them in a little more complex situation. Now these blocks are kicking me in the face, and I'm trying to break it down into comprehensible pieces.
Say I have two blocks in this pseudo code conveniently named blockA and blockB. The first is a simple parameter-less block and it just prints a line. The second takes one parameter xyz of type id:
void (^blockA){ NSLog(#"Doing something"); };
void (^blockB)(id xyz){ [xyz doSomething]; };
When running blockA, I would do something like blockA(); or when I want to target the main queue/thread, I use the dispatch_sync or _async method:
dispatch_sync(dispatch_get_main_queue(), blockA);
But although I know how to dispatch blockB with a parameter like blockB(someObject);, I can't figure out how to explicitly call that one on the main thread. I was looking for something like the next line, but of course that's not how this works:
dispatch_sync(dispatch_get_main_queue, blockB, someObject);
Now I've tried wrapping the block in another block, but to be honest that just doesn't look right and it felt like it was causing more problems than it solved. Is there something other than wrapping blocks to dispatch one block with one or more parameters on the main queue/thread?
Nope. Wrapping blocks is exactly what you have to do in this case. In code:
void (^block)(id someArg) = someBlock;
id object = someObject;
dispatch_async(dispatch_get_main_queue(), ^{
block(someObject);
});
It may look a little strange at first, but this style makes the dispatch APIs so much simpler and the automatic retaining of captured variables makes it possible. I'm a little surprised you ran into problems. What were they?
I'm getting used to blocks too. Honestly I can't see anything cleaner/better than:
dispatch_async(dispatch_get_main_queue(), ^{blockb(someObj);});
Looking at the JSON-Framework source, it makes heavy use of pass by reference in many of the parser method signatures. i.e.
#interface SBJsonParser ()
- (BOOL)scanValue:(NSObject **)o;
- (BOOL)scanRestOfArray:(NSMutableArray **)o;
- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o;
#end
This ends up being used something like this:
id o;
[self scanValue:&o];
// Do something with o
- (BOOL)scanValue:(NSObject **)o {
// Cut down for brevity
return [self scanRestOfDictionary:(NSMutableDictionary **)o];
}
- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o {
// Cut down for brevity
*o = [NSMutableDictionary dictionaryWithCapacity:7];
[*o setObject:#"value" forKey:#"key"];
return YES;
}
What are the benefits to this approach?
EDIT: I'm asking more from a design point of view. I understand what pass by reference is, I'm just wondering when it's appropriate to use it. The design used in SBJsonParser is similar to the API used in NSScanner:
- (BOOL)scanUpToString:(NSString *)stopString intoString:(NSString **)stringValue;
To me, this implies that the string which was scanned is secondary to needing to know if something was scanned. This is in contrast to the API used by NSString:
+ (id)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error;
In that API, the contents of the file is the primary concern, and the NSError reference is used to pass back an error in the event that something goes wrong.
Just after some general thoughts on which API is most appropriate, when.
Those are "output" parameters. They allow the called method to assign a value to your local variable "o". In other words, you're not passing in a reference to an object, but a reference to a local variable.
In your case, the methods return a BOOL to indicate success or failure; therefore, they use output parameters to return other values and objects.
It's really just a style question. It should be consistent across an entire API.
On the one hand, you've got a style where the status code of the call is always returned and output of the call is in the parameter list.
Benefits? You can always check the call result for success. You can easily have multiple return values without changing the style.
Drawbacks? Can't just drop in calls in place of parameters. Harder to chain.
On the other hand, you've got a style where the primary data is returned from the call and any error codes are done through out parameters.
The benefits and drawbacks are essentially inverted.
To be fair, there's a third style: no results are passed out or returned. Instead, exceptions are used.
Benefits? Cleaner looking code.
Drawbacks? Works well for errors, but not so well for status codes that may go along with valid return codes.