-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[quick_actions]Migrates all remaining components to Swift, and deprecate OCMock #6597
[quick_actions]Migrates all remaining components to Swift, and deprecate OCMock #6597
Conversation
} | ||
|
||
/// A default implementation of the `MethodChannel` protocol. | ||
extension FlutterMethodChannel: MethodChannel {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I put this extension in the same file as the protocol. Alternatively we can also use separate files and I am ok either way.
More details discussed in Rule 3(b) of the Swift POP naming convention proposal. Feel free to leave any comments.
} | ||
|
||
/// A default implementation of `ShortcutStateManaging` protocol. | ||
final class DefaultShortcutStateManager: ShortcutStateManaging { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: i put this class in the same file as the protocol, but also ok to use separate files.
More details discussed in Rule 3(b) of the Swift POP naming convention proposal. Feel free to leave any comments.
|
||
// type and localizedTitle are required. | ||
return UIApplicationShortcutItem( | ||
type: serialized["type"] as! String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should not let this plugin crash the production app? Maybe use Assert
to crash debug app and return nil if either serialized["type"] or serialized["localizedTitle"] is nil in release.
Does the original Objective-C API crashes the App if type or localizedTitle is nil? If so, I'm ok with keep the same behavior and follow up with a fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the original Objective-C API crashes the App if type or localizedTitle is nil?
I think so, the API is non-null (and that's why it bridges to non-null String in Swift): https://developer.apple.com/documentation/uikit/uiapplicationshortcutitem/1623372-initwithtype?language=objc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adopting pigeon would solve this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the Objective-C API actually crash if you pass in nil
though? A lot of Objective-C APIs that predate nullability do handle nil
s under the covers, especially since most implementation files aren't wrapped in NS_ASSUME_NULL
to catch the error in analysis. Ideally passing in the wrong types would give an actionable error, but at the least this should not introduce a new crash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Let me try it out.
The dart counterpart also guarantees that this is never null though. So it likely doesn't matter anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried it out - indeed the objc API did not crash - instead it just ignores it.
friendly ping |
packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemServicing.swift
Outdated
Show resolved
Hide resolved
import UIKit | ||
|
||
/// Manages the shortcut related states. | ||
protocol ShortcutStateManaging { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense for there to be a var shortcutItems: [UIApplicationShortcutItem]? { get set }
protocol as well as this one? It looks like DefaultShortcutStateManager
could easily implement ShortcutItemServicing
instead by exposing service.shortcutItems
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The var shortcutItems: [UIApplicationShortcutItem]? { get set }
protocol is just an abstraction to stub UIApplication
. The ShortcutStateManager has extra parsing logic. So it is better not to combine these 2.
An alternative way is to define a ShortcutItemParser
, like this:
protocol ShortcutItemParser {
func parseItems(_ items: [[String, Any]]) -> [UIApplicationShortcutItem]
}
This will make the dependency DAG more "flat". Let me try and see how it goes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated ShortcutStateManager
to ShortcutItemParser
, and renamed ShortcutItemServicing
to AppShortcutControlling
.
The benefit is simpler and more flat dependency tree: Now the QuickActionsPlugin
depends on both ShortcutItemParser
and AppShortcutControlling
, and these 2 subcomponents do not depend on each other anymore.
PTAL thx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that we still want to have a separate AppShortcutControlling
protocol, so that we can stub out the UIApplication.default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShortcutItemParser
SGTM.
But AppShortcutControlling
isn't a capability in the sense the docs mean, in that setting this shortcutItems
collection is not operating on the "implementing" UIApplication
, it's more mutating it. Like the example ProgressReporting
would be reporting on the progress of the thing implementing the protocol.
In addition, "AppShortcutControlling" doesn't exactly make sense in English. How about ShortcutItemProvider
? At the end of the day Swift's naming guidance is purposely very loosey, we should name it in a way that describes what it does, and also makes sense in English.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, Provide
sounds like it only provides something, with only getter and no setters (e.g. AgeProviding
in the style guide).
How about AppShortcutManaging
? it's setting a collection, but also making iOS to update the springboard shortcuts. So it feels like performing an action, rather than just a collection holder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm circling back on this - i think i am fine with the Provider
name (it's not ideal, as explained above), but i can't think of a better name.
Though we want Providing
for protocol name, since it's a capability to provide something (similar to NameProviding
and AgeProviding
in our style guide. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! Thanks for iterating on this with me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to ShortcutItemProviding
(unless @cyanglaz or @stuartmorgan can think of a better name?)
|
||
// type and localizedTitle are required. | ||
return UIApplicationShortcutItem( | ||
type: serialized["type"] as! String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adopting pigeon would solve this.
b48938a
to
1295feb
Compare
/// Services `UIApplicationShortcutItem`s. | ||
protocol ShortcutItemServicing: AnyObject { | ||
/// Controlls app's shortcut behavior. | ||
protocol AppShortcutControlling: AnyObject { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this need AnyObject
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AnyObject
scopes this protocol to reference types (classes). It prevents any value types (enums & structs) to conform to it.
Since this is injected dependency with no value semantics, we want to scope it to reference types. See the NOTE
below:
class QuickActionsPlugin {
// NOTE: If we remove `AnyObject`, we have to use `var` here.
private let controller: AppShortcutControlling
func foo() {
controller.shortcutItems = [] // mutate here
}
}
import UIKit | ||
|
||
/// Manages the shortcut related states. | ||
protocol ShortcutStateManaging { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShortcutItemParser
SGTM.
But AppShortcutControlling
isn't a capability in the sense the docs mean, in that setting this shortcutItems
collection is not operating on the "implementing" UIApplication
, it's more mutating it. Like the example ProgressReporting
would be reporting on the progress of the thing implementing the protocol.
In addition, "AppShortcutControlling" doesn't exactly make sense in English. How about ShortcutItemProvider
? At the end of the day Swift's naming guidance is purposely very loosey, we should name it in a way that describes what it does, and also makes sense in English.
6d5c871
to
fd9968e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
de2266a
to
76d835e
Compare
…and deprecate OCMock (flutter/plugins#6597)
* 19673b341 [camera]: Bump camerax_version (flutter/plugins#6709) * b8282424e [gh_actions]: Bump ossf/scorecard-action from 2.0.4 to 2.0.6 (flutter/plugins#6610) * 2ba4c0a70 [file_selector] Add getDirectoryPaths method to the file_selector_platform_interface. (flutter/plugins#6572) * 89cbf74c8 [quick_actions]Migrates all remaining components to Swift, and deprecate OCMock (flutter/plugins#6597) * 51d084453 [quick_actions] Fix Android integration test flake (flutter/plugins#6688) * b2fe01bc0 [google_sign_in] Correctly passes `serverClientId` to native libs (flutter/plugins#6691)
…ate OCMock (flutter#6597) * [quick_actions]migrate shortcut state manager, deprecate OCMock and use POP * remove objc proj settings * rename shortcut state manager * bump version * run swift-format * nit * remove public_header_files * use shortcut item parser instead of shortcut state manager * some nit * rename AppShortcutControlling to ShortcutItemProviding * nit * do not crash if no type or title * update license
…#115656) * 19673b341 [camera]: Bump camerax_version (flutter/plugins#6709) * b8282424e [gh_actions]: Bump ossf/scorecard-action from 2.0.4 to 2.0.6 (flutter/plugins#6610) * 2ba4c0a70 [file_selector] Add getDirectoryPaths method to the file_selector_platform_interface. (flutter/plugins#6572) * 89cbf74c8 [quick_actions]Migrates all remaining components to Swift, and deprecate OCMock (flutter/plugins#6597) * 51d084453 [quick_actions] Fix Android integration test flake (flutter/plugins#6688) * b2fe01bc0 [google_sign_in] Correctly passes `serverClientId` to native libs (flutter/plugins#6691)
…#115656) * 19673b341 [camera]: Bump camerax_version (flutter/plugins#6709) * b8282424e [gh_actions]: Bump ossf/scorecard-action from 2.0.4 to 2.0.6 (flutter/plugins#6610) * 2ba4c0a70 [file_selector] Add getDirectoryPaths method to the file_selector_platform_interface. (flutter/plugins#6572) * 89cbf74c8 [quick_actions]Migrates all remaining components to Swift, and deprecate OCMock (flutter/plugins#6597) * 51d084453 [quick_actions] Fix Android integration test flake (flutter/plugins#6688) * b2fe01bc0 [google_sign_in] Correctly passes `serverClientId` to native libs (flutter/plugins#6691)
…ate OCMock (flutter#6597) * [quick_actions]migrate shortcut state manager, deprecate OCMock and use POP * remove objc proj settings * rename shortcut state manager * bump version * run swift-format * nit * remove public_header_files * use shortcut item parser instead of shortcut state manager * some nit * rename AppShortcutControlling to ShortcutItemProviding * nit * do not crash if no type or title * update license
This PR completes the Swift migration for quick_actions plugin. The main part is to migrate
FLTShortcutStateManager
using POP. We defined the following new types:MethodChannel
protocol (to whichFlutterMethodChannel
conforms)AppShortcutControlling
protocol (to whichUIApplication
conforms)ShortcutItemParser
protocolThe above naming follows the proposal "Swift POP naming convention".
Note that we have to migrate
FLTQuickActionsPluginTests
too in this PR, because this test depends onShortcutStateManaging
, which is non-objc type that OCMock does not support.If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
flutter/flutter#108750
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.