How does KVC deal with speed and errors? - objective-c

I've been reading about KVC and Cocoa Scripting, and how properties can be used for this. I have a model class in mind, but the element/property data has to be obtained from the Internet. But the design of properties and KVC looks like it assumes fast & in-memory retrieval, while network calls can be slow and/or error-prone. How can these be reconciled?
For speed, do we just say "screw it" and post a waiting icon? (Of course, we should keep things multi-threaded so the UI doesn't stop while we wait.)
If your property is supposed to be always available, we could set it to nil if the resource call gets an error. But we would have no way to get the specifics. Worse would be a property that supports "missing values," then nil would represent that and we would have no spare state to use for errors.
Although Apple-events support error handling, I couldn't use it because between my potentially error-generating model calls and the Apple event, the KVC layer would drop the error to the floor (of oblivion). The Scripting Bridge API saw this problem, since its designers added a secret protocol to handle errors.
Am I wrong? Is there a way to handle errors with KVC-based designs?
Addendum
I forgot to mention exceptions. Objective-C now supports them, but the little I read about them implies that they're meant for catastrophic "instead of straight crashing" use, not for regular error handling like in C++. Except for that, they could've been useful here....

I think I understand what you're asking now. I would say using KVC (or property getters) is not a good way to accomplish what you're trying to do. If the code gets called on the main thread, you will then block that thread. which you don't want to do. As you have discovered you'll also have a hard time returning other state information such as errors.
Instead, you should use block syntax to create an asynchronous method that operates on a background queue. Here is a basic template for what this might look like:
// called from main thread
- (void) fetchDataInBackgroundWithCompletionHandler:(void (^)(id responseData, NSError *error))handler
{
// perform in background
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^()
{
// perform your background operation here
// call completion block on main thread
dispatch_async(dispatch_get_main_queue(), ^{
if(// whatever your error case is)
{
handler(nil, error);
}
else // success
{
handler(responseData, nil);
}
});
});
}
This also gives you the benefit of being able to pass in as many other parameters are you want as well as return as many values as you want in the completion block.
Some very good examples of this pattern can be seen in AFNetworking, which is one of the more popular networking libraries written for iOS. All of the calls in the library can be made from the main queue and will return on the main queue asycnhronously while performing all networking in the background.

Related

Cocoa Scripting: Intercept any Object-first message calls

I am writing my own non-ObjC framework around Cocoa Scripting (think of writing a scriptable Mac app in C, C++ or Java, or in my case, Xojo).
I like to be able to intercept any Object-first method invocation instead of having to add the actual method to the ObjC class (I can't because the framework won't know which message the app code can handle in advance - so it'll instead have to receive and pass on any command message once they come in from the scripting engine).
For instance, any property getters and setters can be intercepted via implementing
-valueForUndefinedKey:
-setValue:forUndefinedKey:
as well as all the methods of the NSScriptKeyValueCoding protocol.
I am looking for a similar way to intercept NSCommandScript messages sent to the method specified in these sdef elements:
<responds-to command="reload">
<cocoa method="reloadList:"/>
</responds-to>
So, instead of implementing reloadList: by adding it to the class methods, I wonder if there's a generic way to catch all such calls.
I found that the class method
+ (BOOL)resolveInstanceMethod:(SEL)sel
gets invoked asking for reloadList:. But the same method is invoked for many other purposes as well, and so I rather not blindly intercept every such call because it would cause a rather severe performance hit if I'd forward them all to a Java function that tells me whether it wants to handle it, for instance.
I hope there's something that lets me tell that this selector is related to a NSScriptCommand before forwarding it further.
After setting a breakpoint into the designated command handling method, I saw the following stack trace:
#0 0x00000001000197db in -[SKTRectangle rotate:]
#1 0x00007fff8ee0b7bc in __invoking___ ()
#2 0x00007fff8ee0b612 in -[NSInvocation invoke] ()
#3 0x00007fff8eeab5c6 in -[NSInvocation invokeWithTarget:] ()
#4 0x00007fff8b82cbde in -[NSScriptCommand _sendToRemainingReceivers] ()
#5 0x00007fff8b82cf39 in -[NSScriptCommand executeCommand] ()
This shows that NSScriptCommand does not appear to use any customizable special forwarding mechanism but uses NSInvocation to call the method.
Such invocations can be intercepted like this:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
// Look for signatures with exactly one ":"
if ([[NSStringFromSelector(aSelector) componentsSeparatedByString:#":"] count] == 2) {
return [NSMethodSignature signatureWithObjCTypes:"#:##"];
} else {
return [super methodSignatureForSelector:aSelector];
}
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
id arg; // The first and only argument is expected to be of type NSScriptCommand*
[anInvocation getArgument:&arg atIndex:2];
if ([arg isKindOfClass:[NSScriptCommand class]]) {
NSLog(#"executing the command...");
// when finished, set the return value (which shall be an NSObject)
id result = nil;
[anInvocation setReturnValue:&result];
} else {
// oops - we cannot handle this
[super forwardInvocation:anInvocation];
}
}
This form of interception works better than using resolveInstanceMethod: because it doesn't get called so often but only for specific purposes such as an NSScriptCommand execution.
The problem with this, however, is that if other code also uses NSInvocation to make calls into the same class for other purposes, and if those calls use a matching selector signature, the above code would intercept those calls and then not handle them, possibly leading to unexpected behavior.
As long as the classes are known to be used only by the scripting engine and have no other behavior (i.e. they're immediate subclasses of NSObject), there is no reason for this to happen. So, in my special case where the classes act only as proxies into another environment, this may be a viable solution.
If it's not a Cocoa-based app then you're probably best to forget about using Cocoa Scripting as it's heavily coupled to the rest of the Cocoa architecture, install your own AE handlers directly using NSAppleEventManager and write your own View-Controller glue between those and whatever you eventually implement your Model in. See also: Scriptability (AppleScript) in a Mac Carbon application
ETA: Come to think of it, you might want to rummage around the web and see if you can dredge up any old C++ AEOM frameworks, as ISTR there were one or two around back in the pre-OS X days. May require some updating, and may or may not be any good (but then CS is rather crappy too), but it'd be far easier than starting completely from scratch as designing and implementing a good, robust, idiomatic (or even simplified) AEOM framework is a giant PITA, even when you do know what you're doing (and hardly anyone does).

Is there a less repetitive way to forward action messages to another object?

I'm making a calculator app to learn Objective-C and maybe improve my OO design skills a bit. In an attempt to do things more MVClike, i have separated the actual do-the-calculator-stuff code from the view controller. For every action, pretty much all the view controller does is tell the "model" to do the operation meant for that action.
Thing is, that gives me a bunch of methods that do basically nothing but forward the action to the model, like this:
- (IBAction)clearAll:(id)sender {
[self.model clearAll];
}
- (IBAction)clearDisplay:(id)sender {
[self.model clearDisplay];
}
- (IBAction)clearMemory:(id)sender {
[self.model clearMemory];
}
- (IBAction)storeMemory:(id)sender {
[self.model storeMemory];
}
- (IBAction)addMemory:(id)sender {
[self.model addMemory];
}
- (IBAction) subtractMemory:(id)sender {
[self.model subtractFromMemory];
}
- (IBAction)recallMemory:(id)sender {
[self.model recallMemory];
}
Objective-C so far seems outrageously flexible with dynamically forwarding messages, and these methods are alike enough to look rather easily automated away. Do they really have to be there? Or is there a less repetitive way to tell the controller to just pass certain messages through to the model (ideally, while stripping off the sender arg)?
I've been looking a bit and trying some stuff with selectors and NSInvocation, but it seems like that'd mess with Interface Builder by taking away all the (IBAction) markers that let me hook up buttons to actions. (I'd prefer if the view didn't have to know or care that the controller's just forwarding to the model in these cases.)
So, is there a less repetitive and/or hacky way? Or is it not worth the trouble? (Or is it a bad idea in the first place? Or is this trying to make the model do too much? Or...)
You can do what Gabriele suggested and it is certainly an example of how dynamic ObjC can be, but you are likely better off avoiding it. As Gabriele said, you'd better know exactly what you are doing and definitely not to overuse such feature. And that often indicates that such feature is likely more trouble than it is worth.
The reality is that your calculator application is a quite contrived for the purposes of driving home the separation inherent to the Model-View-Controller pattern. It is a learning app, as you state.
In reality, no application is ever that simple. You will rarely, if ever, have a field of buttons where that the control layer blindly forwards said functionality on to the model.
Instead, there will be all manners of business logic in that control layer that will may do everything from automating various actions to validation (potentially by querying the model) to updating UI state in response to various actions.
Likely this code will be present from very early in the project, thus that generic forwarding mechanism will quickly become completely unused.
As well, such forwarding mechanisms become funnels full of pain when it comes to debugging. you no longer have a concrete spot to drop a breakpoint, but now have to add conditions. Nor do you have an easy means of finding all the places that might invoke or implement a particular method. As well, it makes following the control flow more difficult.
If you do find yourself with lots of repetitive boiler-plate code, it is more of a sign that your architecture is likely flawed than a sign that you need to inject a spiffy dynamic mechanism to reduce the repetitiveness.
As well, if you were to continue to flesh out your calculator app, how much of your coding time would have been spent doing those repetitive methods vs. all other features in your app? Likely, very very little and, because of their simplicity and convenience to debugging, it is unlikely that said repetitive methods are ever going to incur any significant maintenance cost whereas a spiffy-dynamic bit of trickery (which is very cool and I encourage you to explore that in other contexts) is pretty much guaranteed to require a "Huh. What was I thinking here?!" moment later on.
You can use the dynamic features of the language.
From the Objective-C Runtime Programming documentation
When an object can’t respond to a message because it doesn’t have a method matching the selector in the message, the runtime system informs the object by sending it a forwardInvocation.
So in your case you can implement the forward invocation method as follows
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if ([self.model respondsToSelector:[anInvocation selector]])
[anInvocation invokeWithTarget:self.model];
else
[super forwardInvocation:anInvocation];
}
Note
You have also have to uniform your methods signatures. Either remove the sender parameter or add it to the model's method, otherwise respondsToSelector will return NO and the method won't be called.
In this case forwardInvocation will act as a dispatcher and it will try to send every message not implemented by your controller to the self.model object. If this is not responding to a selector it will call super, very likely resulting in an unrecognized selector exception.
I personally find it very elegant, even though you'd better know exactly what you are doing and definitely not to overuse such feature.

Why does NSOperation example code uses #try & #catch

In Apple's Concurrency Programming Guide the NSOperation subclass examples (both non-concurrent and concurrent varieties) use exception handling and I'm wondering why they are encouraging this style within operations.
Listing 2-4 Responding to a cancellation request
- (void)main {
#try {
BOOL isDone = NO;
while (![self isCancelled] && !isDone) {
// Do some work and set isDone to YES when finished
}
}
#catch(...) {
// Do not rethrow exceptions.
}
}
My understanding is that generally exception handling is not a common practice in Objective-C code - exceptions are essentially programmer errors and should cause the app to crash whereas unexpected inputs are best handled by NSError. (My possibly misinformed understanding comes from things like this and this)
I'm wondering if NSOperations present a particular situation in which exception handling is important, or if this is more the preferred style of the particular author of that guide.
As a side note, some of the NSOperation example code follows this style, other examples do not. Most high-visibility OSS does not use exceptions (AFNetworking, for example).
Your understanding is correct - NSError (or similar) should be used to convey error information, rather than exceptions. Most Objective-C code is not exception-safe and will at the very least leak resources. As a general rule, never let your code leak an exception into anyone else's code - whether Apple's or a 3rd parties. Some 3rd party frameworks may explicitly indicate they are exception safe, but it's rare.
By that principle you can see why you should have a catch-all exception handler in your main method regardless. But there's actually another reason: your operation will be run on a dedicated thread. Exceptions thrown from your operation will propagate up the stack, but no further. The logical caller or owner of the operation won't get them, as they're running on a different thread (or not at all). So leaked exceptions will either kill your whole program, or be swallowed silently with no other indication. Your program may then get stuck in a weird state - since you didn't realise an error occurred, you may continue waiting for the result of your operation that will never arrive.
Additionally, Apple has a section in the Concurrency Programming Guide where they talk about Handling Errors and Exceptions. Their first point on "discrete entities" is alluding to what I said in the previous paragraph:
Handling Errors and Exceptions
Because operations are essentially
discrete entities inside your application, they are responsible for
handling any errors or exceptions that arise. In OS X v10.6 and later,
the default start method provided by the NSOperation class does not
catch exceptions. (In OS X v10.5, the start method does catch and
suppress exceptions.) Your own code should always catch and suppress
exceptions directly. It should also check error codes and notify the
appropriate parts of your application as needed. And if you replace
the start method, you must similarly catch any exceptions in your
custom implementation to prevent them from leaving the scope of the
underlying thread.
Among the types of error situations you should be prepared to handle
are the following:
Check and handle UNIX errno-style error codes.
Check explicit error
codes returned by methods and functions.
Catch exceptions thrown by
your own code or by other system frameworks.
Catch exceptions thrown
by the NSOperation class itself, which throws exceptions in the
following situations:
When the operation is not ready to execute but
its start method is called
When the operation is executing or finished
(possibly because it was canceled) and its start method is called
again
When you try to add a completion block to an operation that is
already executing or finished
When you try to retrieve the result of
an NSInvocationOperation object that was canceled
If your custom code
does encounter an exception or error, you should take whatever steps
are needed to propagate that error to the rest of your application.
The NSOperation class does not provide explicit methods for passing
along error result codes or exceptions to other parts of your
application. Therefore, if such information is important to your
application, you must provide the necessary code.
I think this post and the accompanying answer elaborates very well on the general exception- vs. no exception handling topic!
It is unsafe to throw exceptions in circumstances where resources are
not automatically managed. This is the case of the Cocoa framework
(and neighbor frameworks), as they use manual reference counting.
If you throw an exception, any release call you skip over by unwinding
the stack will result in a leak. This should limit you tothrowing only
if you're certain that you're not going to recover since all resources
are returned to the OS when a process quits.
Unfortunately, NSRunLoops tend to catch all exceptions that propagate
to them, so if you throw during an event, you'll resume to the next
event. This is, obviously, very bad. Therefore, it's better that you
simply don't throw.
This problem is diminished if you use garbage-collected Objective-C,
as any resource represented by an Objective-C object will be properly
released. However, C resources (such as file descriptors or
malloc-allocated memory) that are not wrapped in an Objective-C object
will still leak.
So, all in all, don't throw.
The Cocoa API has several workarounds to this, as you mentioned.
Returning nil and the NSError** pattern are two of them.

Is it worth it to refactor common HTTP request code, performance-wise?

I've been developing an iPhone app, which handed by an experienced developer. I'm just an apprentice programmer and still struggling with practical Objective-C/iOS application development (I have learned Java and PHP on my own, but objective-c is nothing like these to me).
Our app is just another "web-centric" (I don't even know this word is appropriate...) app which heavily relies on server-side operations, making frequent http post request every single time (such as tracking user locations, send messages to another users etc.).
When I was assigned to develop this app, I saw in the code, that every single http request was written inside each method. Each request was done by dispatching another thread, and each action were written for those requests' response accordingly.
E.g.
-(void) methodA {
// Making http request headers...
// Dispatch another thread
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT , 0);
dispatch_async(queue, ^{
// Send synchronous request and handle the response...
});
}
-(void) methodB {
// Making http request headers...
// Dispatch another thread
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT , 0);
dispatch_async(queue, ^{
// Send synchronous request and handle the response...
});
}
The codes like above are every where when the app needs to send request to the server.
I'm wondering, why he didn't create a class that handles http requests.
In Java, you could create a class that make synchronous request to the server:
public class ClassHttpRequest {
public int makePost {
// Send synchronous request and return result...
}
}
Then make an instance of this class and execute it's instance method (in this case, makePost) inside a thread:
public class methodA {
Thread t = new Thread(new Runnable() {
public void run() {
public ClassHttpRequest requestHandler = new ClassHttpRequest();
if (success == requestHandler.makePost()) {
// Handle response...
}
}
}
});
t.start();
}
Is there any performance penalty or issues in creating a class and let it handles frequent http request in Objective-C? Or, it's just simply not "recommended" or something? I have heard that, in Objective-C, it is not common to use try-catch statement for exception handling, because it would consume much resources. I do have read several iOS and Objective-C books (and googled), but such kind of "practical" answer for real application development is hard to find, most of the time it's rather confusing to beginners like me.
I should ask him why he didn't create a such class, but he's away now and I couldn't get in touch with him. Also, I belive that the professionals here in stackoverflow can provide me much more accurate and concise solutions than my predecessor. (I have asked several questions and already got what I wanted to know.)
Thanks in advance.
Normal rules of object-oriented design apply: if it makes sense to represent a HTTP request as a tangible object - in particular, there's a bunch of boilerplate code that's necessary and would otherwise be copy-pasted - then it's probably a good idea to use a class. Otherwise, there's no need. Though in this specific case, is there a reason you're not just using the standard, asynchronous system APIs - NSURLRequest, NSURLConnection, NSURLDownload, etc?
#try/#catch are by definition used for exception handling, and should be used as necessary. If you skimp on them your code may fail in unnecessarily interesting ways (e.g. leaving locks dangling) or to unnecessarily degrees (e.g. crashing completely instead of simply failing a specific operation). What you shouldn't do is use them for flow control - unlike other languages, Objective-C exceptions are for programmer errors, "impossible" conditions, and other such events. Unfortunately a lot of existing Objective-C code is not exception-safe, so while you should utilise them you shouldn't rely on them.
They're not particularly expensive in any of the runtimes you're likely to use these days - the #try is very cheap, almost free. Only if an exception is thrown is there any significant work done, and since you should only be seeing them in very bad situations - i.e. not frequently - the performance cost is irrelevant.
Refactoring the code is a question of balance. The current code is verbose and a bit repeating, but refactoring it into a separate class will introduce a new indirection, an intermediate API. It’s probably worth it if the new API has a decent semantics, like if you can create a SomeNetworkService class with methods like postStatus, listItems and such. The interface should be asynchronous, something like this:
typedef void (^StatusCompletionBlock)(BOOL success, NSError *error);
- (void) postStatus: (NSString*) status withCompletion: (StatusCompletionBlock) completion;
This should make the code more readable, more DRY and even more testable, since you can replace the whole SomeNetworkService object with a stub. So that would be certainly worth it.
The performance hit of sending one extra message is not worth mentioning. Generally speaking, people worry about performance too much. If you can sacrifice performance for better readability, 99 times out of 100 it’s worth it.

Returning errors in objective-c

Im newish to objective-c and am starting to wonder what is the common/standard/proper way for handling and catching errors?
It seems like it might be possible to use NSError to do this, is that a good idea or a hijack of cocoa?
I'm pretty sure that's what the NSError class is there to do - give details about errors. The most common pattern you'll see is a method that takes a pointer to an NSError object, as in:
- (id)doSomethingWithArgument:(id)arg error:(NSError **)error
The method returns some value (or possibly nil) for the result of doing something, but if the call failed will place an NSError object at the pointer passed with details about the failure. Your documentation is responsible for specifying what gets returned if the method does encounter an error.
The other method that comes to mind is the #throw-#catch block; however, in Objective-C #throwing an exception can be rather computationally expensive, and it's usually only recommended to do so in truly exceptional situations.
Edit: wow, turns out a lot of people have really strong opinions about #throwing exceptions. To sum up the (quite helpful) commentary on the issue:
Throwing exceptions should most often deal with programmer error (situations that should never happen, and the like); exceptions should not be used for ordinary error handling. Instead, use the error method demonstrated above or post instances of NSNotification.
If you do wind up making extensive use of #throw/#catch blocks, be very careful about the logic surrounding them. Objective-C provides a lot of ways to detach methods to run in other threads, or delay execution, etc. Be very careful to account for all those possibilities when you write your code.
Finally, another very valid point:
If you do use the error object passed to a method, the return value should indicate it. Don't try to do both (return a partially valid object and set the error object).