According to this Stackoverflow post: Selectors or Blocks for callbacks in an Objective-C library ,
blocks seem to be the future of ObjC. However, much like anonymous functions, blocks feel more like "drafting" an implementation. Also, due to its "embedded" nature, I fear that overusing them will break modularity in the sense of unit-testing or "testable" OOP.
I couldn't find much guideline on how to test blocks and how to coordinate tests for blocks and regular methods. Are there good resources for this topic?
I created 3 macros that wait for the block to be executed in a unit test so the assertions can be made inside the block.
#define TestNeedsToWaitForBlock() __block BOOL blockFinished = NO
#define BlockFinished() blockFinished = YES
#define WaitForBlock() while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) && !blockFinished)
Example:
- (void)testWaitForBlock {
TestNeedsToWaitForBlock();
[target selectorWithInlineBlock:^(id obj) {
// assertions
BlockFinished();
}];
WaitForBlock();
}
Not sure if you've already tried it, but I use Kiwi for unit testing my iOS applications. Its not amazingly documented but it can be used for testing blocks.
https://github.com/allending/Kiwi
Take a look at the 'capturing arguments' under 'mocks and stubs' on their wiki. You can use this to capture a block thats being passed. This is really useful for code thats asynchronous - you can call the method you want to test, capture some completion block and then immediately execute the block synchronously, making your asynchronous code effectively synchronous.
In reference to blocks feeling like drafting an implementation - they don't have to be like that. I define blocks as a would a method, not inline. In fact I often write a method to return the block, making the code clean and easily testable.
Not sure if thats what you were looking for.
- (void)testWaitForBlock {
[target selectorWithInlineBlock:^(id obj) {
// assertions
BlockFinished();
}];
//use this to keep runloop is alive ,you can do anything.
NSDate * date = [NSDate dateWithTimeIntervalSinceNow:10];
[[NSRunLoop currentRunLoop]runUntilDate:date];
}
Related
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.
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.
The void (^)(void) syntax of the 'completion' argument type implemented by the UIViewController method:
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion
has piqued my curiosity and I have been unable to find any documentation for it. Please could someone help explain its purpose/meaning?
Many thanks in advance.
Here's the discussion of blocks from my book:
http://www.apeth.com/iOSBook/ch03.html#_blocks
There's an example there, but here's an example that's closer to the sort of thing you're asking about:
[self transitionFromViewController:fromvc
toViewController:tovc
duration:0.4
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:nil
completion:^(BOOL done){
[tovc didMoveToParentViewController:self];
[fromvc removeFromParentViewController];
}];
The completion block takes one parameter, a BOOL called "done", but this is not used by its code. The idea is that the animation is performed and then the code in the completion block is run.
It's very important to be comfortable with blocks because they are the way of the future. For example, view animation in iOS 4 uses them, as explained in the "Block Based View Animation" section of my book (read first about the old way, then read about the new iOS 4 way):
http://www.apeth.com/iOSBook/ch17.html#_view_animation
In iOS 5 blocks are even more important; there are more and more situations where they are not optional.
Also blocks are the way to use GCD (grand central dispatch), which is far and away the best way to do multi-threading.
That would be for a completion block. A block is a snippet of code that may be submitted as an argument (often seen, as here, for completion handling) to an API. There are many features of blocks, including the ability to reference memory and maintain state.
See documentation on this increasingly popular feature of Obj-C:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html
Blocks provide what might be considered callback behavior (typically achieved with delegation or notification), but they allow the programmer to include the logic of the completion behavior in the same context as the initiating action, making the code more expressive and conveying the complete progression of intended behavior concisely.
I was looking through one of Apple's XCode tutorials and came across something that looked like this inside the implementation of a class method:
void (^foo)(void);
foo = ^(void) {
NSLog(#"Hello, World!");
};
foo();
Now obviously this is some kind of function declaration, implementation, and usage. However, I'd like to know more about it, what it is called, and what its limitations and advantages are. My searches online are turning up nothing relevant. Can anyone point me in the proper direction?
They're called blocks. You can think of a block as a chunk of code that you can pass around to other parts of your program. They were added by Apple to its C and Objective-C compilers relatively recently, but some newer APIs take blocks instead or in addition to selectors or function pointers.
Blocks and block variables.
Here's some reading:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html
http://pragmaticstudio.com/blog/2010/7/28/ios4-blocks-1
http://thirdcog.eu/pwcblocks/
I have been doing some testing with ObjectiveResource (iOS->Rails bridge). Things seem to work, but the library is synchronous (or maybe not, but the mailing list that supports it is a mess).
I'm wondering what the pitfalls are to just running all calls in a performSelectorInBackground... in small tests it seems to work fine, but that's the case with many things that are wrong.
The only caveat I've noticed is that you have to create an Autorelease Pool in the method called by performSelectorInBackground (and then you should only call drain and not release?).
performSelectorInBackground: uses threads behind the scenes, and the big thing with threads is that any piece of code touched by more than one is a minefield for race conditions and other subtle bugs. This obviously means drawing to the screen is off-limits outside the main thread. But there are a lot of other libraries that are also not threadsafe, and any code using those is also tainted.
Basically, thread-safety is something you have to intentionally put in your code or it's probably not there. ObjectiveResource doesn't make any claims to it, so already I would be nervous. Glancing at the source, it looks like it mainly uses the Foundation URL loading machinery, which is threadsafe IIRC. But the ObjectiveResource code itself is not. Just at a glance, all of the class methods use static variables, which means they're all subject to race conditions if you performSelectorInBackground: more than once with code that uses them.
It looks like the 1.1 branch on their Github has explicit support for async through a ConnectionManager class. Probably better off using that (though this is essentially unmaintained code, so caveat emptor).
So are you actually experiencing any issues? Or are you just anticipating them?
Running on a background thread shouldn't give you any issues, unless you try to update a UI element from that same background thread. Be sure to forward any UI-related activities to the main thread. For example (pseudo):
- (void)viewWillAppear:(BOOL)animated {
[self performSelectorInBackground:#selector(refreshTableView)];
[super viewWillAppear:animated];
}
- (void)refreshTableView {
// Where _listOfObjects is used to populate your UITableView
#synchronized(self) {
self._listOfObjects = [MyDataType findAllRemote];
}
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
Note also (as above) that if you are changing the value of any instance variables on the background thread, it's important that you synchronize on self to prevent any other threads (like the main thread) from accessing objects in the _listOfObjects array while it is being updated or set. (Or you may "get" an incomplete object.)
I'm not 100% positive (comments are welcome), but I believe that if you declare the _listOfObjects property as atomic, you won't need to worry about the synchronized block. Though, you would need the synchronized block regardless of the #property declaration if, instead of reassigning the value of the property, you were instead making changes to a single, persistent instance. (Eg. Adding/removing objects from a static NSMutableArray.)