Simple NSSpeechRecognizer code, not working! - cocoa

I noticed NSSpeechRecognizer in ADC library and I found it to be very interesting, so to play with it I prepared a simple application which will just listen the command and if recognized it displays it in log.
The code used is:
- (id)init {
if (self = [super init]) {
// Insert code here to initialize your application
NSArray *cmds = [NSArray arrayWithObjects:#"A",#"B", #"C",#"alpha",#"beta",#"vodka",#"wine",nil];
recog = [[NSSpeechRecognizer alloc] init]; // recog is an ivar
[recog setCommands:cmds];
[recog setDelegate:self];
}
return self;
}
- (IBAction)listen:(id)sender
{ NSLog(#"listen:");
if ([sender state] == NSOnState) { // listen
[recog startListening];
} else {
[recog stopListening];
}
}
- (void)speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(id)aCmd {
NSLog(#"speechRecognizer: %#",(NSString *)aCmd);
}
I tried it many times for the commands registered but I was unable to get none of the messages in log, in delegate :(
There was always some noise in the background.. could this be the reason for it or I have done something wrong in the code??
Can anyone suggest me some solution for it??
Thanks,
Miraaj

Code looks fine so far.
The NSSpeechRecognizer is a bit tricky sometimes and refuses to listen to the right words. Did you try different words?
Did you try setting startListening as default?
I wrote a little tutorial some time ago. Its in german language but maybe it will help you anyway or you use some translation tool.
http://cocoa-coding.de/spracherkennung/nsspeechrecognizer1.html

Related

NSTextField with NSFormatter results in broken continuous binding

I have a textfield which has to be unique so I added my custom NSFormatter (see below)
The formatter works, as you can see on the screenshot, but the continuous binding, which I am using is broken, so for example the bound text does no longer get updated in real-time.
I found a possible cause here, but I don't know how to work around this problem and re-enable the continuous binding:
...
12. If the view has an NSFormatter attached to it, the value is
formatted by the NSFormatter instance. Proceed to Step 17.
...
17. The updated value is displayed in the user interface.
So it looks like it's intentionally skipping the steps we want. This
is very annoying. I tried NSValueTransformer, but adding that to an
editable NSTextField makes it non-editable.
My formatter
- (BOOL)getObjectValue:(out id *)obj forString:(NSString *)string errorDescription:(out NSString **)error {
if([string isNotEqualTo:#"todo-invalid-value"]){
*obj = string;
NSLog(#"YES");
return YES;
} else {
if(error){
*error = #"ERROR: not allowed";
}
return NO;
}
}
- (NSString *)stringForObjectValue:(id)obj {
return (NSString *)obj;
}
Working validation
Please note that the title of the list item should be updated with the text, that I entered in the textfield.
I ran into the same problem over the weekend, and eventually discovered a post from 2008 by Yann Disser on the cocoa-dev mailing list which shed some light on my problem.
I had an existing NSFormatter that was working fine and when I broke down the components, so I spent a little more time on it this morning and located Yann's post.
The key is that you need to return a different object than the one that is passed in. It's subtle, but the docs say: If conversion is successful, upon return contains the object created from string.
The problem I was having stemmed from the fact that the NSString that was coming in was actually an NSMutableString and was getting modified later.
Here's the code modified to return [NSString stringWithString: string], which should fix your problem:
- (BOOL)getObjectValue:(out id *)obj forString:(NSString *)string errorDescription:(out NSString **)error {
if([string isNotEqualTo:#"todo-invalid-value"]){
*obj = [NSString stringWithString: string];
NSLog(#"YES");
return YES;
} else {
if(error){
*error = #"ERROR: not allowed";
}
return NO;
}
}

How to use IKScannerDeviceView in Cocoa

How can I use IKScannerDeviceView to scan a document inside of my app?
I tried adding an IKScannerDeviceView into my view through IB and setting its delegate to my app delegate (which implements the IKScannerDeviceViewDelegate), but when I run the app I get a view with the buttons Show Details and Scan, and only Show Details is enabled and when I click it nothing happens.
I have a scanner plugged in and I can scan through Image Capture, but not through my app.
Does anybody have a good tutorial on how to use it?
I was finally able to figure out how to use IKScannerDeviceView.
Your class must implement the following delegates:
IKScannerDeviceViewDelegate, ICScannerDeviceDelegate, ICDeviceBrowserDelegate
and you need to have an IKScannerDeviceView in your window, with its delegate set to the class implementing IKScannerDeviceViewDelegate
To start using it, you must create an ICDeviceBrowser like so:
ICDeviceBrowser *mDeviceBrowser = [[ICDeviceBrowser alloc] init];
mDeviceBrowser.delegate = self;
mDeviceBrowser.browsedDeviceTypeMask = ICDeviceLocationTypeMaskLocal|ICDeviceLocationTypeMaskRemote|ICDeviceTypeMaskScanner;
[mDeviceBrowser start];
Then implement the delegate methods in a manner similar to this:
- (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner;
{
[scanner requestOpenSession];
}
- (void)deviceBrowser:(ICDeviceBrowser*)browser didAddDevice:(ICDevice*)addedDevice moreComing:(BOOL)moreComing
{
if ( (addedDevice.type & ICDeviceTypeMaskScanner) == ICDeviceTypeScanner )
{
[scannerView setScannerDevice:(ICScannerDevice*)addedDevice];
}
}
-(void)didRemoveDevice:(ICDevice*)removedDevice
{
[removedDevice requestCloseSession];
}
Then if all goes right, your IKScannerDeviceView will be able to interact with your scanner!

Get variable from void function in Objective C

I'm VERY new to Objective C and iOS development (like 5 hours new :-). I've got some code that calls an API to authenticate a user and returns a simple OK or FAIL. I can get the result to write to the console but what I need to do is get that result as part of my IBAction.
Here's the IBAction code:
- (IBAction) authenticateUser
{
[txtEmail resignFirstResponder];
[txtPassword resignFirstResponder];
[self performAuthentication];
if (authResult == #"OK")
What I need is for authResult to be the JSON result (OK or FAIL). Here is the code that gets the result:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"%#", responseString);
[responseData release];
NSMutableDictionary *jsonResult = [responseString JSONValue];
if (jsonResult != nil)
{
NSString *jsonResponse = [jsonResult objectForKey:#"Result"];
NSLog(#"%#", jsonResponse);
}
}
Thank you so much for any help and sorry if I'm missing something obvious!
I'm a little confused as to what's going on here... it looks like your -performAuthentication method must start an asynchronous network request via NSURLConnection, and your connection's delegate's -connectionDidFinishLoading: gets to determine the result of the request. So good so far? But your -authenticateUser method expects authResult to be determined as soon as -performAuthentication returns. If the network request is asynchronous, that's not going to happen. If I'm following you, I think you need to do the following:
Fix up -connectionDidFinishLoading: so that it actually sets authResult based on the Result value in jsonResponse. I'm sure you'd get around to this at some point anyway.
Change -authenticateUser such that it doesn't expect to have an answer immediately. You've got to give the network request a chance to do its thing.
Add another method, possibly called -authenticationDidFinish or something along those lines. Everything currently in -authenticateUser from the 'if (authResult...' to the end goes in this new method.
Call the new method from -connectionDidFinishLoading:.
Fix your string comparison. If you want to compare two strings in Cocoa, you say (for example):
if ([authResult isEqualToString:#"OK") { }

Run method on main thread from another thread

My model class has to get some data from the internet. So I decided to run it on another thread so the ui doesn't freeze.
So when an object wants some data it first asks the model using a method of this type:
- (void)giveMeSomeData:(id)object withLabel:(id)label {
objectAsking= object;
theLabel= label;
NSThread* thread= [[NSThread alloc] initWithTarget:self selector:#selector(getTheDataFromInternet) object:nil];
[thread start];
}
- (void)getTheDataFromInternet {
//getting data...
theData= [dataFromInternet retain]; //this is the data the object asked for
[self returnObjectToAsker];
}
- (void)returnObjectToAsker {
[objectAsking receiveData:theData withLabel:theLabel];
}
As I'm still a newbie, can you tell me if it's a good pattern?
Thanks!
Your setup is pretty much correct. You never want to initiate any sort of network connection on the main thread.
As it currently stands, -returnObjectToAsker will be executed on the background thread.
You'd probably be interested in -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:].
Or if you wanted to something with Grand Central Dispatch (iOS 4+, Mac OS X 10.6+), you could do:
#import <dispatch/dispatch.h>
- (void)giveMeSomeData:(id)object withLabel:(id)label {
dispatch_async(dispatch_get_global_queue(0,0), ^{
//this runs on a background thread
//get data from the internet
dataFromTheInternet = ...;
dispatch_async(dispatch_get_main_queue(), ^{
[object receiveData:dataFromTheInternet withLabel:label];
//this runs on the main thread. Use theData
});
});
}
Since the blocks capture their environment, you wouldn't even have to save off object and label into ivars. :)

How to bind a control to a singleton in Cocoa?

I have a singleton in my FTP app designed to store all of the types of servers that the app can handle, such as FTP or Amazon S3. These types are plugins which are located in the app bundle. Their path is located by applicationWillFinishLoading: and sent to the addServerType: method inside the singleton to be loaded and stored in an NSMutableDictionary.
My question is this:
How do I bind an NSDictionaryController to the dictionary inside the singleton instance? Can it be done in IB, or do I have to do it in code? I need to be able to display the dictionary's keys in an NSPopupButton so the user can select a server type.
Thanks in advance!
SphereCat1
I found / made up the answer to this: I simply override the init method so when it's called from the XIB file, it still returns the singleton. I then provide a method named realInit to do an actual initialization the first time init is called.
Code:
-(id)init
{
#synchronized(self)
{
if (_sharedInstance == nil)
{
_sharedInstance = [[VayprServerTypes alloc] realInit];
}
}
[self release];
return _sharedInstance;
}
-(id)realInit
{
if (self = [super init])
{
serverTypesArray = [[NSMutableArray alloc] init];
}
return self;
}
EDIT: Of course you'll need to define _sharedInstance as a static variable at the top of your class implementation:
static ClassTypeGoesHere *_sharedInstance;
ALSO EDIT: Since you now know for sure that your init method will be called at least once, you can go ahead and replace your normal singleton sharedInstance method with this:
+(ClassTypeGoesHere *)sharedInstance
{
return _sharedInstance;
}
If anyone sees any obvious problems with this design, please let me know!
SphereCat1

Resources