-
Notifications
You must be signed in to change notification settings - Fork 318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Visual Instruction Presentation Customization #1530
Visual Instruction Presentation Customization #1530
Conversation
…d by `InstructionPresenter`.
@@ -538,6 +538,10 @@ extension NavigationViewController: RouteMapViewControllerDelegate { | |||
} | |||
return roadName | |||
} | |||
|
|||
@objc public func label(_ label: InstructionLabel, willPresent instruction: VisualInstruction, as presented: NSAttributedString) -> NSAttributedString? { |
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.
Curious, why does NavigationViewController need to implement the delegate method?
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.
This is just plumbing the delegate method through the view-controller hierarchy, just like we do here for a NavigationMapViewDelegate
method or here for the same method (label(_:willPresent:as:)
), being routed through RouteMapViewController
.
It's not really accurate to say that the NavigationViewController
is implementing the delegate method so much as it's merely passing the message onto its delegate.
- parameter presented: the formatted string that is provided by the instruction presenter | ||
- returns: optionally, a customized NSAttributedString that will be presented instead of the default, or if nil, the default behavior will be used. | ||
*/ | ||
@objc optional func label(_ label: InstructionLabel, willPresent instruction: VisualInstruction, as presented: NSAttributedString) -> NSAttributedString? |
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.
A delegate method’s first argument should always be the delegator. Is the delegator an InstructionLabel, or something else? Can it be either or two classes? That would be an antipattern in Cocoa.
Does this “will” method’s name make the implementation’s purpose clear enough? Is it clear that it’s an opportunity to override the presentation?
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.
To answer your first question, yes, the label is the delegator.
- parameter presented: the formatted string that is provided by the instruction presenter | ||
- returns: optionally, a customized NSAttributedString that will be presented instead of the default, or if nil, the default behavior will be used. | ||
*/ | ||
@objc optional func label(_ label: InstructionLabel, willPresent instruction: VisualInstruction, as presented: NSAttributedString) -> NSAttributedString? |
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 Objective-C signature of this method is currently -label:willPresent:as:
. I think it should be -…:willPresentVisualInstruction:label:presentedAttributedString:
or somesuch.
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.
Ah, right you are. Good catch. Will fix.
// Mark: VisualInstructionDelegate | ||
extension ViewController: VisualInstructionDelegate { | ||
func label(_ label: InstructionLabel, willPresent instruction: VisualInstruction, as presented: NSAttributedString) -> NSAttributedString? { | ||
guard exampleMode == .customInstruction else { return nil } |
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.
With VoiceController(_:WillSpeak:Instruction:)
, returning nil omits the voice instruction. I'm guess that's not the case here? In reality, I can't really think of a use case where a developer would want to show nothing though.
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.
That's kind of the idea. The utility of "I only want to override default behavior under specific circumstances" seems to outweigh the utility of "it's nice to say 'show nothing' via nil
instead of NSAttributedString()
". In this specific example you could also implement default behavior by returning presented
, but I think we should get into the general habit of using a "returning nil means the delegate has no answer to the delegator, and thus default behavior should be used" pattern in our delegation, as otherwise you kind of force the developer to implement logic if they implement the optional delegate function. Not a super great pattern.
With #1514 coming down the line, can you think of anything that might make this play nicely with the lanes view? Maybe returning nil hides/omits the view? #1530 (comment) |
@@ -69,6 +71,16 @@ class InstructionsBannerViewIntegrationTests: XCTestCase { | |||
|
|||
super.tearDown() | |||
} | |||
|
|||
func testCustomVisualInstructionDelegate() { |
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.
Also add a test for returning nil.
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.
- Test for
nil
response
|
||
func testCustomVisualInstructionDelegate() { | ||
let view = instructionsView() | ||
view.instructionDelegate = TextReversingDelegate() |
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.
instructionDelegate
will be deallocated immediately because it's weak. Keep a local ref to TextReversingDelegate()
. (×2)
… it's visual instruction delegate.
Implements #1503.
InstructionPresenter
.To-do:
/cc @mapbox/navigation-ios