Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

moonman239

Cancelled
Original poster
Mar 27, 2009
1,541
32
I'm working on an app that uses Nuance's speech recognizer. The way I have it set up is I have a conditional statement in the recognizerDidFinishWithResults. If the condition is not met, then the app is supposed to rerecord the user's voice. I suspect it's because I'm calling a method that starts the same recognizer that caused recognizerDidFinishWithResults to be fired. I tried setting the recognizer variable to nil, but that did not help. What should I do?
 
How do you know it is not being called?



Post your code

Just so I don't risk divulging too much information about the app, I'm going to post a modified version.

Code:
 if ([result isEqualToString:myString])
    {
        self.myLabel.text = @"I love you, too!";
    }
    else
    {
        if ([result length] > 0)
        {
            self.myLabel.text = @"I hate you.";
        }
        else
        {
            self.myLabel.text = @"You're giving me the silent treatment, eh?";
        }
[self startRecognizer];
    }

Note: The only piece of code between the two brackets of the method that affects the recognizer is the [self startRecognizer]. The real code is not complicated.
 
Last edited:
Just so I don't risk divulging too much information about the app, I'm going to post a modified version.

Code:
 if ([result isEqualToString:myString])
    {
        // do something
    }
    else
    {
        if ([result length] > 0)
        {
            // do something else
        }
        else
        {
            // No speech detected.
        }
[self startRecognizer];
    }

Note: The only piece of code between the two brackets of the method that affects the recognizer is the [self startRecognizer]. The real code is not complicated.

Sorry, the code you gave us says absolutely nothing. If you're not willing to post your code, then the best solution is to keep reading books until you're familiar enough with the language to solve it on your own.
 
Sorry, the code you gave us says absolutely nothing. If you're not willing to post your code, then the best solution is to keep reading books until you're familiar enough with the language to solve it on your own.

This is still not my code, but it's close enough.
Code:
 if ([result isEqualToString:myString])
    {
        self.myLabel.text = @"I love you, too!";
    }
    else
    {
        if ([result length] > 0)
        {
            self.myLabel.text = @"I hate you.";
        }
        else
        {
            self.myLabel.text = @"You're giving me the silent treatment, eh?";
        }
[self startRecognizer];
    }
 
Last edited:
Make a test case.

Write the code so that no matter what happens, the recognizerDidFinishWithResults method always starts the recognizer again. Then test how that works.

If the test works, and the recognizer is always correctly restarted, then you can make a slightly different test, such as one that only tests the length of the utterance and simply logs either "long" or "short".

If the test fails, then it's reasonable to conclude that you can't restart a recognizer. At least not from a recognizerDidFinishWithResults method. You can then work on coming up with an alternative approach, which you should then test in the same way. That is, test it by making it start a recognizer after every utterance.


FWIW, the above is just a simple use of making test cases and finding out how they work. Making test cases is a fundamental skill for discovering how things really work. And discovering how things really work is the essence of debugging.

Test cases almost always start with the simplest thing that can give useful results. Since your basic question hinged on whether a recognizer can be restarted or not in a recognizerDidFinishWithResults method, that's what it should test and no more. It should definitively answer exactly one question, and provide a consistent answer every time the test case is invoked.

If the test case produces different answers, then there is some external variable not being accounted for. You need to do account for it and put it into the question the test case is intended to answer. In other words, the question isn't specific enough about an answer, or isn't specific enough about the preconditions.

Once you have a consistent answer for that one question, you can proceed to write test cases that answer other questions that may come up.


The key to writing test cases is to have a clear statement of what the test case will test (the specific question), and have it do no more than that. If you don't know exactly what you're testing for, or you can't write it in a way that gives a definitive answer every time, then you need to correct those things.
 
Make a test case.

Write the code so that no matter what happens, the recognizerDidFinishWithResults method always starts the recognizer again. Then test how that works.

If the test works, and the recognizer is always correctly restarted, then you can make a slightly different test, such as one that only tests the length of the utterance and simply logs either "long" or "short".

If the test fails, then it's reasonable to conclude that you can't restart a recognizer. At least not from a recognizerDidFinishWithResults method. You can then work on coming up with an alternative approach, which you should then test in the same way. That is, test it by making it start a recognizer after every utterance.


FWIW, the above is just a simple use of making test cases and finding out how they work. Making test cases is a fundamental skill for discovering how things really work. And discovering how things really work is the essence of debugging.

Test cases almost always start with the simplest thing that can give useful results. Since your basic question hinged on whether a recognizer can be restarted or not in a recognizerDidFinishWithResults method, that's what it should test and no more. It should definitively answer exactly one question, and provide a consistent answer every time the test case is invoked.

If the test case produces different answers, then there is some external variable not being accounted for. You need to do account for it and put it into the question the test case is intended to answer. In other words, the question isn't specific enough about an answer, or isn't specific enough about the preconditions.

Once you have a consistent answer for that one question, you can proceed to write test cases that answer other questions that may come up.


The key to writing test cases is to have a clear statement of what the test case will test (the specific question), and have it do no more than that. If you don't know exactly what you're testing for, or you can't write it in a way that gives a definitive answer every time, then you need to correct those things.

Got it.

I suppose I should have mentioned that when startRecognizer is called, the recognizer variable is set to an SKRecognizer object with programmer-defined properties. The method code looks somewhat like this:

Code:
-(void)startRecognizer:
{
recognizer = [SKRecognizer initWithProperties:// properties];
}

Perhaps the method that is supposed to initialize the recognizer just returns the same object. Or perhaps iOS doesn't like to reinitialize an object that was previously initialized in the same run.
 
OK. After taking everything but [self startRecognizer], I have come to the conclusion that I cannot set the recognizer to a new instance of SKRecognizer. Because my app uses automatic reference counting, I can't deallocate the variable. Based on prior experience, I think I can safely say that having the app set recognizer to nil first will not help.
 
Perhaps the method that is supposed to initialize the recognizer just returns the same object. Or perhaps iOS doesn't like to reinitialize an object that was previously initialized in the same run.

Two sentences containing "perhaps". Sounds like you should write two test cases, where you can test each hypothesis.
 
Two sentences containing "perhaps". Sounds like you should write two test cases, where you can test each hypothesis.

I just set a breakpoint in startRecognizer just so I could watch the recognizer variable. I launched the app twice. Each time the app calls startRecognizer, the alphanumeric phrase next to the recognizer variable in the variable watching window changes.
 
OK, I solved the problem. All I had to do was tell my app to disconnect from the speech server, then reconnect.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.