开发者

Risks of using performSelectorInBackground?

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 cavea开发者_StackOverflow中文版t 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.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜