Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Reland "iOS spell-checker ObjC #32941" #34356

Merged
merged 1 commit into from
Jul 11, 2022

Conversation

cyanglaz
Copy link
Contributor

@cyanglaz cyanglaz commented Jun 28, 2022

Things added to the original PR:

  1. Make UITextChecker lazily intialized.
  2. Convert the method channel result format to be the same as Android so the framework code could be shared.
  3. Move method channel out of the SpellCheckerPlugin so the pattern matches other plugins in FlutterEngine.

Part of flutter/flutter#34688

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See testing the engine for instructions on
    writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Comment on lines +644 to +648
FlutterSpellCheckPlugin* spellCheckPlugin = _spellCheckPlugin.get();
[_spellCheckChannel.get()
setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
[spellCheckPlugin handleMethodCall:call result:result];
}];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the 3rd difference between the original PR, I moved the method channel setup out of FlutterSpellCheckPlugin

Comment on lines 158 to 151
- (NSString*)toFormattedString {
return FormatSpellCheckResult(_misspelledRange.location,
_misspelledRange.location + _misspelledRange.length - 1,
[_suggestions copy]);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the 2nd different between the original PR. Instead of formatting the result as a dictionary in my original PR: https://github.com/flutter/engine/pull/32941/files#diff-1c2372162cba7041e14181d7d080cbb0c66eeb44e9cd75379ab8969646e3087bR154-R159

I formatted as a String that matches the android format: https://github.com/flutter/engine/blob/main/shell/platform/android/io/flutter/plugin/editing/SpellCheckPlugin.java#L108-L110
Note that there is a typo in the android documentation, it is suppose to be \n not /n

// UITextChecker is an expensive object to initiate, see:
// https://github.com/flutter/flutter/issues/104454. Lazily initialate the UITextChecker object
// until at first method channel call. We avoid using lazy getter for testing.
_textChecker = [[UITextChecker alloc] init];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1st difference between the original PR, the UITextChecker object is initialized during the first method channel call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The laziness is typically implemented inside a property getter:

- textChecker {
  if (!_textChecker) 
    _textChecker = ...
  return _textChecker
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it would be hard to test. For example, if I want to test the textChecker is nil at initialization, i couldn't because as soon as i call the getter, it is initialized.
My comment explained why we avoided a lazy getter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah sorry i miss-read that part.

@cyanglaz cyanglaz requested a review from hellohuanlin June 28, 2022 19:27
@cyanglaz
Copy link
Contributor Author

Adding @hellohuanlin as the reviewer as the reviewer of the original PR @jmagman is OOO.

@cyanglaz cyanglaz marked this pull request as ready for review June 28, 2022 19:27
@skia-gold
Copy link

Gold has detected about 2 new digest(s) on patchset 3.
View them at https://flutter-engine-gold.skia.org/cl/github/34356

Copy link
Contributor

@hellohuanlin hellohuanlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main question is about whether to reinvent an in-house serialization format


// Spell check results will be encoded as a string representing the span of that result, with
// the format "start_index.end_index.suggestion_1\nsuggestion_2\nsuggestion_3".
static NSString* FormatSpellCheckResult(NSUInteger startIndex,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Is this the same format as the android?
  2. Why are we using a custom serialization? can we just use more standardized ones like JSON or CSV?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it is matching android, im not sure the detailed reason behind not using JSON.
cc @camsim99

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason behind this was to avoid unnecessary overhead as brought up in my design doc. I think I discussed with @cyanglaz doing some testing to see if this would significantly slow things down and I would be open to that since that's the main concern!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camsim99 Are you worrying that JSON serialization/parsing is significantly slower (or taking more space) than the proposed custom format?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think JSON is a better approach, it shouldn't be slower.
For example in java: https://stackoverflow.com/questions/12155800/how-to-convert-hashmap-to-json-object-in-java

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought there was a discussion about this format when @camsim99 did the Android engine PR, but I couldn't find it (code in the PR). I think @GaryQian was involved if I remember right?

From my memory the concern with JSON was the repetition of keys for every suggestion, which for a long document there could be many.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If memory is a concern, it seems to me that we should limit the misspelled word that the API returns.

If we write our own formatter and parser, we also have to consider the performance of them, which creates an additional maintenance burden.

Also, I was a little confused myself last week. JSON serialization is already supported by default on MethodChannel, so we don't really have to do an extra serialization in this PR if we choose to use JSON. I will revert that code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I talked to Gary a little bit and we agreed that using JSON seems to be the way to go for now. If it turns out to be slow, we can revisit using a custom format.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Sounds like a solid plan!


// Get all the misspelled words and suggestions in the entire String.
//
// The result will be formatted as am NSArray.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an

// UITextChecker is an expensive object to initiate, see:
// https://github.com/flutter/flutter/issues/104454. Lazily initialate the UITextChecker object
// until at first method channel call. We avoid using lazy getter for testing.
_textChecker = [[UITextChecker alloc] init];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The laziness is typically implemented inside a property getter:

- textChecker {
  if (!_textChecker) 
    _textChecker = ...
  return _textChecker
}

@skia-gold
Copy link

Gold has detected about 2 new digest(s) on patchset 5.
View them at https://flutter-engine-gold.skia.org/cl/github/34356

@flutter-dashboard
Copy link

Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change).

If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review.

Changes reported for pull request #34356 at sha 0b5e6ce

@@ -0,0 +1 @@
import Foundation
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accedentialy checked this in, will remove

@cyanglaz
Copy link
Contributor Author

cyanglaz commented Jul 6, 2022

@hellohuanlin Updated the format to JSON, ptal

cc @camsim99

@skia-gold
Copy link

Gold has detected about 1 new digest(s) on patchset 6.
View them at https://flutter-engine-gold.skia.org/cl/github/34356

@cyanglaz cyanglaz force-pushed the reland_ios_check_check branch from c2d5961 to f2511d8 Compare July 6, 2022 16:45
Revert "Revert "iOS spell-checker ObjC" (flutter#33570)"

This reverts commit b1fafb9.

method channel move out of plugin

tests

cleanup

fix

fix typo

remove swift file

change format to JSON

nil error

format

revert format code
@cyanglaz cyanglaz force-pushed the reland_ios_check_check branch from 65d6824 to 8847696 Compare July 7, 2022 17:18
@cyanglaz
Copy link
Contributor Author

Friendly ping @hellohuanlin
We can delay the discussion of the result format. I can always come back to add a new PR to update the format if we end up using the "startIndex.endIndex.suggestions" format.

I'm not sure about the skia-gold check. There is no bot message saying the gold is fixed but the gold error comment didn't show up after re-basing so I assume it was an upstream issue and re-base fixed it?

cc @godofredoc Do you think we can improve the skia-gold bot so that it is clearer that the skia-gold issue is fixed after a commit?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
autosubmit Merge PR when tree becomes green via auto submit App platform-ios will affect goldens
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants