Migrating Custom Push Row to Eureka 4.1 - eureka-forms

I'm having quite a hard time migrating a custom row from a previous version of Eureka (around 3.0) to Eureka 4.1. The custom row is a custom push row so the label can have multiple lines and so the view controller that is pushed can have a custom section header. There may be a better way to accomplish that than having a custom row, so that is one possible solution, but I'm not sure if that's a possibility.
So there are 2 problems: The custom row and the the custom selector view controller. Here's the custom row:
open class _StackedPushRow: SelectorRow<StackedPushCell, CustomSelectorViewController<String>> {
public typealias StackedRow = PushRow<String>
var dontClearWhenDisabled: Bool = false
required public init(tag: String?) {
super.init(tag: tag)
cellProvider = CellProvider(nibName: "StackedPushCell")
presentationMode = .show(controllerProvider: ControllerProvider.callback {
return CustomSelectorViewController<Cell.Value> { _ in } },
onDismiss: { vc in
self.cell.update()
_ = vc.navigationController?.popViewController(animated: true)
})
}
}
/// A generic inline row where the user can pick an option from a presented view controller
public final class StackedPushRow: _StackedPushRow, RowType {
required public init(tag: String?) {
super.init(tag: tag)
}
}
and here's the custom selector view controller:
public final class CustomSelectorViewController<T: Equatable>: SelectorViewController<T> {
open override func viewDidLoad() {
super.viewDidLoad()
form.first?.header = HeaderFooterView.caliberStyleSectionHeader(title: row.title ?? "")
}
static func presentationMode<T: Equatable>() -> PresentationMode<SelectorViewController<T>> {
return .show(controllerProvider: ControllerProvider.callback {
return CustomSelectorViewController<T> { _ in }
}, onDismiss: { vc in
_ = vc.navigationController?.popViewController(animated: true)
})
}
}
Here are the errors for the custom row:
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:78:29:
Generic type 'SelectorRow' specialized with too many type parameters
(got 2, but expected 1)
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:85:9:
'super' members cannot be referenced in a root class
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:86:9:
Use of unresolved identifier 'cellProvider'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:88:9:
Use of unresolved identifier 'presentationMode'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:98:20:
Type 'StackedPushRow' does not conform to protocol 'BaseRowType'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:98:20:
Type 'StackedPushRow' does not conform to protocol 'RowType'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:98:20:
Candidate has non-matching type '(String?, (Self) -> Void)'
(Eureka.RowType)
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:98:20:
Type 'StackedPushRow' does not conform to protocol 'Taggable'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:98:20:
Type 'StackedPushRow' does not conform to protocol 'TypedRowType'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:111:9:
Use of unresolved identifier 'validationOptions'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomRows/StackedPushRow.swift:141:9:
'StackedPushRow' is not a subtype of 'BaseRow'
Here are the errors for the custom selector view controller:
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomSelectorViewController.swift:12:64:
Type 'T' does not conform to protocol 'OptionsProviderRow'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomSelectorViewController.swift:14:24:
Method does not override any method from its superclass
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomSelectorViewController.swift:15:9:
'super' members cannot be referenced in a root class
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomSelectorViewController.swift:17:9:
Use of unresolved identifier 'form'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomSelectorViewController.swift:17:80:
Use of unresolved identifier 'row'
/Users/rod/Documents/Development/Caliber/CaliberiOS/H2O/_iOS/H2O/UI/Common/CustomSelectorViewController.swift:22:52:
Argument passed to call that takes no arguments
I've read the issues section on Github and seen examples of others running into this, but every time I try to put the examples in to practice, I run into other problems and I just keep running in circles. I could really use some help.
Thanks.

SelectorRow now only takes a generic Cell type but no view controller. The SelectorViewController is defined by the presentationMode. You should declare your row like:
open class _StackedPushRow: SelectorRow<StackedPushCell>
For your CustomSelectorViewController you need to pass the rowType you are going to use as generic type. That row type must conform to OptionsProviderRow, like ListCheckRow for example.

Related

How do I extend a widget.Button so that it has a new method ID in fyne?

I did this but it doesn't work
type buttonWithID struct {
widget.ListItemID
}
func newButtonWithID(button widget.Button) *buttonWithID {
newButton := &buttonWithID{}
newButton.ExtendBaseWidget(newButton)
newButton.ListItemID = 0
return newButton
}
and it returns this error:
newButton.ExtendBaseWidget undefined (type *buttonWithID has no field or method ExtendBaseWidget)
If you want to extend Button then your struct must embed the widget.Button type. Extra fields would be added below that.
See the tutorial at https://developer.fyne.io/tutorial/extending-widgets

How to trigger visitInputObject method on custom directive?

I'm building a custom directive in which I'm hoping to validate entire input objects. I'm using the INPUT_OBJECT type with the visitInputObject method on SchemaDirectiveVisitor extended class.
Every time I run a mutation using the input type then visitInputObject does not run.
I've used the other types/methods like visitObject and visitFieldDefinition and they work perfectly. But when trying to use input types and methods they will not trigger.
I've read all the available documentation I can find. Is this just not supported yet?
Some context code(Not actual):
directive #validateThis on INPUT_OBJECT
input MyInputType #validateThis {
id: ID
someField: String
}
type Mutation {
someMutation(myInput: MyInputType!): SomeType
}
class ValidateThisDirective extends SchemaDirectiveVisitor {
visitInputObject(type) {
console.log('Not triggering');
}
}
All the visit methods of a SchemaDirectiveVisitor are ran at the same time -- when the schema is built. That includes visitFieldDefinition and visitFieldDefinition. The difference is that when we use visitFieldDefinition, we often do it to modify the resolve function for the visited field. It's this function that's called during execution.
You use each visit methods to modify the respective schema element. You can use visitInputObject to modify an input object, for example to add or remove fields from it. You cannot use it to modify the resolution logic of an output object's field. You should use visitFieldDefinition for that.
visitFieldDefinition(field, details) {
const { resolve = defaultFieldResolver } = field
field.resolve = async function (parent, args, context, info) {
Object.keys(args).forEach(argName => {
const argDefinition = field.args.find(a => a.name === argName)
// Note: you may have to "unwrap" the type if it's a list or non-null
const argType = argDefinition.type
if (argType.name === 'InputTypeToValidate') {
const argValue = args[argName]
// validate here
}
})
return resolve.apply(this, [parent, args, context, info]);
}
}

Check if property or method exists at runtime? Check if Trait exists at runtime?

Looking for the proper way to do
if(self.MyProperty) { /* ... */ }
error: attempted access of field MyProperty on type MyType, but no field with that name was found
or
if(self.MyMethod){ /* ... */ }
error: attempted to take value of method MyMethod on type MyType
As a last resort, at least how does one check if a Trait is Implemented?
This concept doesn't exist in Rust. While there is some limited downcast capability through Any, this should be used as a last resort. What you should do is create a new trait that exposes all of these decisions for you.
Reusing your example of a my_method method:
trait YourTrait {
fn try_my_method(&self, arg: SomeArg) -> Option<MyMethodResult> {
None
}
}
impl YourTrait for SomeType {
fn try_my_method(&self, arg: SomeArg) -> Option<MyMethodResult> {
Some(self.my_method(arg))
}
}
In your code you can then call
if let Some(result) = self.try_my_method() {
/* ... */
}

TypeScript method type signature redundant

Maybe I'm seriously missing something, but I'm unable to get rid of a syntax problem with all my classes.
Here is an example :
class Foo {
bar: (x: string, y: number) => string = (xx: string, yy: number) : string => {
// do some stuff...
};
}
Since I'm enforcing type declarations using tslint, ALL my methods are written like this. It's horrible. Having to copy paste the arguments part, renaming the args names between the type declaration and the lambda declaration is soooo painfull.
So : is there a better way to combine type signature and lambda declaration without all the knee jerking ? I sincerely hope I have missed something and hope this is not "by design" ! :)
You need to configure TSLint to enforce types but ignore the type of the functions:
typedef enforces type definitions to exist. Rule options:
"call-signature" checks return type of functions
"parameter" checks type specifier of function parameters
"property-declaration" checks return types of interface properties
"variable-declaration" checks variable declarations
"member-variable-declaration" checks member variable declarations
You can use a file like this one to configure TSLint. And read this to learn more about how to configure it.
Edit:
If you're targeting ES5, you can also do something like this:
var bar = (x: string, y: number) : string => {
// do some stuff...
};
class Foo {
get bar () { return bar; }
}
var test = (new Foo).bar('hello', 3);
Or:
class Foo {
get bar () {
return (xx: string, yy: number): string => {
// do some stuff...
};
}
}
This way the method's context is preserved and it also exists on the prototype. There's also no need to copy the argument types, TSC will infer them.

Check protocol conformance when protocol contains an enum in Swift?

In Swift, in order to check protocol conformance with is or as? downcasting you must mark the protocol with the #objc attribute. Once you mark a protocol with that attribute it seems you can not have a protocol with an enum as a property because enums cannot be represented in Objective-C.
enum Language:String {
case English = "English"
case Spanish = "Spanish"
case German = "German"
}
#objc protocol Humanizable {
var language:Language { get set }
}
You'll get an error: error: property cannot be marked #objc because its type cannot be represented in Objective-C
Here is full example: http://swiftstub.com/475659213/
In the example if you change the Language to String then it works fine.
This is not an answer, but I did spot a compile error in your 'swift stub', Human should be defined as follows:
class Human:Humanizable {
var name:String = "Frank"
var language:Language = .English
}
You were trying to create an enum instance from a string literal.
I am a little surprised that protocol conformance checking requires #obj - that's just ugly!

Resources