TextExpander / TextExpanderTouchSDK

TextExpander touch SDK
85 stars 13 forks source link

stringByExpandingAbbreviations not expanding on first attempt #4

Closed youens closed 10 years ago

youens commented 10 years ago

Using 2.3.1, I'm attempting this:

 SMTEDelegateController *textExpander = [[SMTEDelegateController alloc] init];
 NSString *expandedValue = [textExpander stringByExpandingAbbreviations:value];

On the first try, this never expands. If I call the same method again, it expands every time. It feels as if there is a race condition of some sort. It's my assumption it shouldn't return until snippets are loaded and everything is in order. Any ideas?

SmilinBrian commented 10 years ago

Oops -- the first call does prompt the snippets to be loaded and initialized, and most of the method correctly waits for any possibly load/init to complete.

But there is an optimization to avoid examining larger-than-needed chunks of the input string. That computation of "the longest snippet abbreviation length" fails to wait for the init to complete, so it returns zero, and then everything gets "optimized" out -- doh!

Thanks for pointing this out, sorry for the inconvenient inconsistency. We will address in next release.

youens commented 10 years ago

Great! Thanks so much. :+1:

SmilinBrian commented 10 years ago

I should have mentioned: If needed in the meantime, you could use [SMTEDelegateController expansionStatusForceLoad: YES snippetCount: nil loadDate: nil error: &myError] to force the snippets to load synchronously before calling stringByExpandingAbbreviations:.

youens commented 10 years ago

Noted, that should work great. :)

Edit: Though, in testing, that doesn't seem to change the behavior if I insert that above or below the first line of my example above. I'm not submitting an update for a couple weeks, so it's not a huge hurry if there will be a fix to the original method.

youens commented 10 years ago

Just a bump here to say that I'm still seeing this behavior. We're about to push a release of Launch Center Pro, so was hoping to find some workaround if you know of any. Current status:

SMTEDelegateController *textExpander = [[SMTEDelegateController alloc] init];

NSError *error;
[SMTEDelegateController expansionStatusForceLoad:YES snippetCount:nil loadDate:nil error:&error];
if (error) {
    NSLog(@"Error: %@", error.localizedDescription);
}

// returns "ddate" on the first run, the date thereafter.
NSString *expandedValue = [textExpander stringByExpandingAbbreviations:"ddate"];

(no error is returned)

I suppose I can use a global SMTEDelegateController instance, and ask for a snippet on launch to get things primed. Though, in some cases we have incoming URLs that have snippets in them, and they get executed immediately.

SmilinBrian commented 10 years ago

I see now why the workaround that seemed like it should have worked is not working, and it is one of those "worst possible combination of mistakes" -- ugly and sad.

Here is the ugly workaround that should actually work:

SMTEDelegateController *textExpander = [[SMTEDelegateController alloc] init];

// First, force a load/reload if needed (but it occurs on background queue)
[textExpander willEnterForeground];
// Now ask for an attributed string expansion. It doesn't have the troublesome optimization, so it
// will try to expand, which will sync against the background queue kicked off before, forcing
// it to complete
NSAttributedString *forceSync = [textExpander attributedStringByExpandingAbbreviations: [[NSAttributedString alloc] initWithString: @"bogus"]];

// This should work now
NSString *expandedValue = [textExpander stringByExpandingAbbreviations: @"ddate"];

Sorry about the mess. We have one other equally vexing but fairly obscure problem, but we're not quite ready for a new release just yet.

youens commented 10 years ago

Thanks!