FMDB: Does calling a method to make a query in the inDatabase block work the same way? - fmdb

I'm trying to remove some database records, and I have a wrapper class around my FMDB class. What I'm wondering, is if I can call this class method from the inDatabase block?
[_dbQueue inDatabase:^(FMDatabase *db) {
// Do some magic here to get 1234
[myObject deleteWithId:1234]; // This calls executeUpdate:#"DELETE..."
}];

If you're using the latest FMDB, it should crash on you (if your other method is using inDatabase: as well). Recursive inDatabase: calls aren't advised.

Related

How to return multiple results from Asynchronous method?

Note: This question doesn't have anything to do with the language used, i.e, Swift/ Objective-C
I can't seem to get my head around how such a problem can be solved.
How an asynchronous method which processes data continuously ,return back these processed values to a function?
Example Class structure of -> ClassName
A method named -(void)infoCallBack , this is the method you have to call to get returns continuously.
Inside -(void)infoCallBack -> an asynchronous method [self startRecording]is there, which does audio recording asynchronously using AudioQueues by using a callback method void AudioInputCallback(..param..).
Finally Inside void AudioInputCallback(..param..) -> a method -(void) processAudio is there, which continuously processes data and gives us an integer number.
How to call a method like [ClassName infoCallBack] in such a way that we keep getting all these processed integers continuously?
Edit : I have searched SO, and came across completion handler blocks : although completion handlers only return a value once after completionHandler() is called. Moreover, another problem in this method was how to pass around this completionHandler to multiple methods in the className Structure as shown.
I came across delegates, it said that when distinct values are being returned continuously and state of something changes, then we should call a delegate. But I was stuck at how I would return values after I call the function infoCallBack from ClassName, i.e, [ClassName infoCallBack] which continuously can feed the person calling this function with the values being processed.
Actually I don't completely understand your question but I will give you the answer in my understanding
In my opinion, you can use block to handle process update.
typedef void (^ProcessHandlerBlock) (NSInteger i);
- (void)infoCallBackWithProcessHandlerBlock:(ProcessHandlerBlock)block {
[self startRecordingWithProcessHandlerBlock:(ProcessHandlerBlock)block];
}
- (void)startRecordingWithProcessHandlerBlock:(ProcessHandlerBlock)block {
[self audioInputCallbackWithParam1:#"1" param2:#"2" processHandlerBlock:(ProcessHandlerBlock)block];
}
- (void)audioInputCallbackWithParam1:(id)param1 param2:(id)param2 processHandlerBlock:(ProcessHandlerBlock)block {
[self processAudioWithProcessHandlerBlock:(ProcessHandlerBlock)block];
}
- (void)processAudioWithProcessHandlerBlock:(ProcessHandlerBlock)block {
// Assume this is your process method callback
[NSTimer scheduledTimerWithTimeInterval:1.f repeats:YES block:^(NSTimer * _Nonnull timer) {
// After receive integer, pass it to block.
block(1);
}];
}
When you want to use them, call
[self infoCallBackWithProcessHandlerBlock:^(NSInteger i) {
NSLog(#"%l", i); // Do whatever you want here
}];
Inside the completion block of infoCallBackWithProcessHandlerBlock method, you can use result integer to do what you want.
I can't seem to get my head around how such a problem can be solved.
From the rest of what you've written I suspect you can get your head around this, you probably just need a rest. You've found the answer already without realising...
I have searched SO, and came across completion handler blocks : although completion handlers only return a value once after completionHandler() is called.
The phrase "completion handler block" might be written as "a block used as a completion handler" - a block is just a block, you can call it as many times as needed, store it in variables, etc. While a completion handler is typically only called once a, say, result reporter might be called multiple times.
Moreover, another problem in this method was how to pass around this completionHandler to multiple methods in the className Structure as shown.
A block is a kind of object and like other objects your class instance might need to use in many methods it doesn't need to be passed around but can be stored in an instance variable. For ease of use first declare your a shorthand for the block type, say:
typedef void (^SampleHandler)(int i);
then declare a suitable instance variable:
#implementation ClassName
{
SampleHandler mySampleHandler;
}
now use this like any other instance variable - initialise it (mySampleHandler = ...;), use it to call the block (mySampleHandler(42);`)
I came across delegates, it said that when distinct values are being returned continuously and state of something changes, then we should call a delegate. But I was stuck at how...
Blocks and delegates are often used for similar purposes, you can use either to solve your problem in essentially the same way - store the block/delegate reference in an instance variable, call the block/delegate method to return a value. You just have to decide which suits your use case best:
A block is a function. A block is created inline, usually at the call site, and can reference (and sometimes modify) variables in the environment where it is created. Like any function it is (usually) a single-operation thing - pass argument(s), produce a side-effect/return a result.
A delegate is an object. Like any other object it requires an interface/implementation. Like any object it can have multiple methods, so its a multi-operation thing.
In your case - returning a value - a block is probably the best option, but you need to decide.
HTH

Closures in Swift, blocks in Objective-C: their usefulness and when to use

I've found an Objective-C SocketIO library and am trying to implement it in my first Swift app. Here's the code I'm trying to port:
__weak typeof(self) weakSelf = self;
self.socket.onConnect = ^()
{
weakSelf.socketIsConnected = YES;
[weakSelf mapView: weakSelf.mapView didUpdateUserLocation: weakSelf.mapView.userLocation];
};
From my limited understanding ^() {} is a block in Objective C. I've looked into it and closures seem to be a loose equivalent Swift. My first obvious question is how do I get the same result in Swift?
I've tried the following but get the error fatal error: unexpectedly found nil while unwrapping an Optional value (lldb):
self.socket.onConnect = { () -> Void in
println("Connected!")
}
Also, behind the scenes what's happening here? An asynchronous callback function would seem appropriate but wasn't used and I'd like to understand why.
UPDATE
As pointed out by #jtbandes, socket was in fact Nil as this code was running outside of the connection callback (I know, a very silly mistake). Solution to first question:
SIOSocket.socketWithHost(server) { (socket: SIOSocket!) in
self.socket = socket
self.socket.onConnect = { () -> Void in
println("Connected!")
}
}
Objective-C blocks and Swift closures are more than loose equivalents. They are direct equivalents.
A block/closure is an anonymous function that inherits it's enclosing scope.
I'm still working in Objective-C, so I'm used to its terminology. I'll use those terms
Blocks are useful in lots of ways.
Completion code is one example.
Without blocks, if you're setting up an async networking class, you might give it a delegate property, and define a protocol with callbacks that the class uses to notify it's delegate about events like download complete, errors, etc.
This makes for a lot of message handling infrastructure in lots of different places. You have to define a protocol. You have to add a delegate property to the networking class. You have to implement a set of delegate messages in the client class. You may have to pass context information to the callbacks, etc.
With blocks, you invoke a method that asks for a networking service, and provide a completion block. When the service is complete, it invokes the provided code block. You might add parameters to the completion block like a pointer to the data, a success boolean, or whatever is appropriate. The code block can have access to all the variables defined in its enclosing scope, which can be very helpful.
You can also save blocks into collections, you can use blocks in sort methods, and int lots of other cases.
The code you posted simply sets a block property on the object in question, self.socket. It looks like it is a block of code that gets called after a socket connection is established.
There are direct equivalents to this in Swift. I've only poked around in Swift however, so I'll leave it to others to help you with the translation.
I suggest browsing through Apple's classes for ideas on how to use blocks. Take a look at NSURLConnection and NSURLSession if you're interested in async networking. Take a look at the block-based view animation methods that take an animation block and a completion block. Those will give you an idea of the ways you can use blocks for handling async events, or passing code to a class to get work done.
Another interesting use of blocks is in handling collections like arrays. There are methods that take an NSComparator block and sort an array, and there are methods that will enumerate through an array, performing a block of code on each element and/or selecting a subset of the elements and returning an index set of the array indexes.
Duncan

Can someone explain what this piece of code is doing...[ Instantiating a specific object from a class ]

I need some clarification on what or how the object below is being created.
Mechanically, I understand that this is creating an instance to particular button located within the tableview but I'm not quite sure of the method call itself. Can someone please explain to me what's going on with the script within the block? Is there a special name for this?
[OAUtility likePhotoInBackground:self.userPhotoObject block:^(BOOL succeeded, NSError *error) {
OAPhotoHeaderView *actualHeaderView = (OAPhotoHeaderView *) [self tableView:self.tableView viewForHeaderInSection:button.tag] ;
...
}];
Thanks!
This code call method likePhotoInBackground:block on OAUtility class.
You pass self.userPhotoObject as a first parameter and block which pass two parameters succeeded and error. Inside that block (I believe it's completion one) you call another method which return actualHeaderView object, subclass of OAPhotoHeaderView
The code you posted is not creating an object. It's invoking a class method in the class OAUtility, and passing that method a block of code.
The method is likePhotoInBackground:block:
It looks like the likePhotoInBackground:block: method takes 2 parameters, a "photo object" and a block of code.
Code blocks are kind of like C function pointers. They are executable code that can take parameters and return a result.
In this case, the block does not return a result. It takes a BOOL named succeeded, and a pointer to an NSError object.
It looks like the code in the block fetches a header view from a particular section of a table view, based on a button's tag value.
Aside from that, it's hard to know more about what's going on. We would need to know about the OAUtility class and it's methods, and about the setup of the table view, it's buttons, etc.

How can I put a block with multiple arguments into an NSOperationQueue?

I have defined a block like this:
void (^observerBlock) (id aTrigger, id aContext, void(^aTriggerCallbackBlock)(id aTContext)) = ....
Now I want to put it into an NSOperationQueue and get executed concurrently. But NSOperationQueue's instance method addOperationWithBlock: only allows argument like this: (void (^)(void))block.
How can I put my block with multiple arguments into an NSOperationQueue? Thanks.
One way to do this is to subclass the NSOperation or NSBlockOperation classes to create a specialized operation class then just add the properties you need to the subclass instead of passing the values as arguments.
Another way is to just reference the variables you need within the block and when the block gets created it will copy the references/values. If you need to be able change these values you can use __block on your variables you're referencing inside the block.

Creating a type-ahead UISearchDisplay with asynchronous network calls in iOS

One view of my iOS application is a UISearchDisplay. I have designed it as a type-ahead search, so that whenever the user enters a new character the table is re-populated. I have done this by implementing the UISearchDisplayDelegate protocol method:
searchDisplayController:shouldReloadTableForSearchString:
In this method I take the string provided and append it to my query URL. I then create a new NSURLConnection and submit a new asynchronous request. I receive and append data via the delegate method:
connection:didReceiveData:
Once the connection has finished downloading the data, via the method:
connectionDidFinishLoading
I pass the data to an instance of NSXMLParser. The data that is receive is an XML file of all the contacts in my database which match the given string. Once the data has finished being parsed I reload the table.
My Problem: If the user types in text fast enough, there will be multiple connection and parsing tasks going on at the same time. This is an issue because I have one instance of NSMutableData which I append data to and parse. Hopefully you can see where I am going with this.
Does anyone have any suggestions for improving my implementation and/or solving this critical-section problem?
NSXMLParser is not asynchronous. This one trips a lot of people up, since they assume that it is due to its use of delegate callback methods. However, actually the parse method doesn't return until all the parsing is finished.
So while you may have multiple connections going at once, you won't have multiple parsing operations happening unless you've multithreaded it yourself.
To solve the multiple connections problem, how about instead of having one single NSMutableData you have one per connection? There are a number of ways to do that: you might want to look at answers to the following questions for ideas.
Cocoa: Checks required for multiple asynchronous NSURLConnections using same delegate functions?
Managing multiple asynchronous NSURLConnection connections
There is a nice implementation described at Cancellable asynchronous searching with UISearchDisplayController
The gist of the solution is such:
Create a NSOperationQueue instance where you'll perform your search operation and save it into a property of your UISearchDisplayDelegate implementation, let's name it searchQueue.
Implement searchDisplayController:shouldReloadTableForSearchString: method. Note that this method returns a BOOL value, which signals the UISearchDisplayController instance to reload the table view. The method could be implemented like so:
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString {
if ([searchString isEqualToString:#""] == NO) {
[self.searchQueue cancelAllOperations];
[self.searchQueue addOperationWithBlock:^{
NSArray *results = // fetch the results from
// somewhere (that can take a while to do)
// Ensure you're assigning to a local variable here.
// Do not assign to a member variable. You will get
// occasional thread race condition related crashes
// if you do.
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Modify your instance variables here on the main
// UI thread.
[self.searchResults removeAllObjects];
[self.searchResults addObjectsFromArray:results];
// Reload your search results table data.
[controller.searchResultsTableView reloadData];
}];
}];
return NO;
} else {
[self.searchResults removeAllObjects];
return YES;
}
}
Don't forget to cancel any pending operations when the user dismisses the search UI.
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
[self.searchQueue cancelAllOperations];
}

Resources