Cannot convert value of generic associated type of protocol to expected argument type
The generic T
in your function and the associated type T
in your protocol aren't the same T
. Inside the function, T
is referring to the type that is implementing the protocol so the associatedtype is T.T
inside of the function. Your arrays and the return value would have to be using T.T
.
This also means that you will need an additional parameter to your function because the [[T.T]]
return value isn't enough for the compiler to infer what type T
is.
This should work (I changed the generic parameter to U
because all the T
s are confusing):
func dataSource<U: UniqueInit>(initializer: U.Type, nrRowsInSection: Int...) -> [[U.T]] {
var result: [[U.T]] = []
for nrRows in nrRowsInSection {
var row: [U.T] = []
for _ in 0 ..< nrRows {
row.append(U.uniqueInit())
}
result.append(row)
}
return result
}
Alternatively, you could define your function as an extension on UniqueInit
which would eliminate the need for the generics:
extension UniqueInit {
func dataSource(nrRowsInSection: Int...) -> [[T]] {
var result: [[T]] = []
for nrRows in nrRowsInSection {
var row: [T] = []
for _ in 0 ..< nrRows {
row.append(Self.uniqueInit())
}
result.append(row)
}
return result
}
}
Cannot convert value of type 'T?' to expected argument type 'T?'
You need to use an associatedtype
in your protocol so all functions/variables in the protocol uses the same type because otherwise each function with a <T>
will be using a different type
Example (simplified
protocol PostDataProviderProtocol{
associatedtype T
func getItemAt(index:Int)-> T?
func replaceItemAt(index:Int, item:T?)
}
Then in your class you can use it as
class BaseDataProvider<SomeType> {
internal var _itemsPerPage:Int = 0
internal var _page:Int = 0
internal var _endpoint:String = ""
internal var cachedData:[SomeType?] = []
}
extension BaseDataProvider: PostDataProviderProtocol {
typealias T = SomeType
func hasNext() -> Bool {
true
}
func getItemAt(index: Int) -> T? {
self.cachedData[index]
}
func getItems() -> [T] {
return self.cachedData as! [T]
}
}
Swift generic func cannot convert value of type to expected argument type
That's a compiler bug. Had the same issue when Xcode 10 came out.
Adapt your method to the following:
func importArray<T: ImportableUniqueObject>(from exercisesDict: [[String: Any]], transaction: BaseDataTransaction) -> [T] where T.ImportSource == [String: Any] {
let managedObjects = try? transaction.importUniqueObjects(Into<T>(), sourceArray: jsonObjects)
}
Though I recommend do not do force-try when importing.
Also see: https://bugs.swift.org/browse/SR-8945
Swift: cannot convert value of type 'SomeTypeT' to expected argument type 'SomeType_'
The following code worked for me.
struct PageData<T> {
let item: T
let pageNumber: Int
}
protocol PagedServiceProvider: class {
associatedtype T
var pageData: PageData<T>? { get set }
func fetchPage(page: Int, completion: @escaping (PageData<T>?) -> Void)
}
class TestPagedServiceProvider: PagedServiceProvider {
var pageData: PageData<String>?
func fetchPage(page: Int, completion: @escaping (PageData<String>?) -> Void) {
completion(pageData)
}
}
Cannot convert value of type 'Int' to expected argument type 'Int' in generic
func notify<Int>(data: Int, value: Int, at indexPath: IndexPath?) {
buttonSelection.updateTag(tag:value, for:indexPath)
}
This is not how you implement a method that takes Int
. That <Int>
means you have a generic method with a parameter called Int
. It's not the integer type Int
but name of the generic parameter, same as <T>
:
If you declare a generic method in a protocol you cannot implement just one type, you have to implement all the types.
It's possible you actually want to use a protocol with an associated type and not generics:
protocol NotifyDataSelected: class {
associatedtype T
func notify(data: T, value:T, at indexPath: IndexPath?)
}
extension MainButtons: NotifyDataSelected {
typealias T = Int
func notify(data: Int, value: Int, at indexPath: IndexPath?) {
}
}
Swift Generics: Cannot convert value of type to expected argument type
Swift 4.1 Update
This is a bug that was fixed in this pull request, which will make it into the release of Swift 4.1. Your code now compiles as expected in a 4.1 snapshot.
Pre Swift 4.1
This just looks like you're just stretching the compiler too far.
It can deal with conversions from arrays of sub-typed elements to arrays of super-typed elements, e.g
[A]
to[SomeProtocol]
– this is covariance. It's worth noting that arrays have always been an edge case here, as arbitrary generics are invariant. Certain collections, such asArray
, just get special treatment from the compiler allowing for covariance.It can deal with conversions of functions with super-typed parameters to functions with sub-typed parameters, e.g
(SomeProtocol) -> Void
to(A) -> Void
– this is contravariance.
However it appears that it currently cannot do both in one go (but really it should be able to; feel free to file a bug).
For what it's worth, this has nothing to do with generics, the following reproduces the same behaviour:
protocol SomeProtocol {}
class A : SomeProtocol {}
func f1(listener: (A) -> Void) {}
func f2(listener: ([A]) -> Void) {}
func f3(listener: () -> [SomeProtocol]) {}
func g() {
let l1: (SomeProtocol) -> Void = { _ in }
f1(listener: l1) // NO ERROR
let l2: ([SomeProtocol]) -> Void = { _ in }
f2(listener: l2)
// COMPILER ERROR: Cannot convert value of type '([SomeProtocol]) -> Void' to
// expected argument type '([A]) -> Void'
// it's the same story for function return types
let l3: () -> [A] = { [] }
f3(listener: l3)
// COMPILER ERROR: Cannot convert value of type '() -> [A]' to
// expected argument type '() -> [SomeProtocol]'
}
Until fixed, one solution in this case is to simply use a closure expression to act as a trampoline between the two function types:
// converting a ([SomeProtocol]) -> Void to a ([A]) -> Void.
// compiler infers closure expression to be of type ([A]) -> Void, and in the
// implementation, $0 gets implicitly converted from [A] to [SomeProtocol].
f2(listener: { l2($0) })
// converting a () -> [A] to a () -> [SomeProtocol].
// compiler infers closure expression to be of type () -> [SomeProtocol], and in the
// implementation, the result of l3 gets implicitly converted from [A] to [SomeProtocol]
f3(listener: { l3() })
And, applied to your code:
f2(ofType: A.self, listener: { l2($0) })
This works because the compiler infers the closure expression to be of type ([T]?) -> Void
, which can be passed to f2
. In the implementation of the closure, the compiler then performs an implicit conversion of $0
from [T]?
to [SomeProtocol]?
.
And, as Dominik is hinting at, this trampoline could also be done as an additional overload of f2
:
func f2<T : SomeProtocol>(ofType type: T.Type, listener: ([SomeProtocol]?) -> Void) {
// pass a closure expression of type ([T]?) -> Void to the original f2, we then
// deal with the conversion from [T]? to [SomeProtocol]? in the closure.
// (and by "we", I mean the compiler, implicitly)
f2(ofType: type, listener: { (arr: [T]?) in listener(arr) })
}
Allowing you to once again call it as f2(ofType: A.self, listener: l2)
.
Swift generics error: Cannot convert value of type 'TypeT' to expected argument type 'Type_'
You are using a non-generic concrete type MyModel
in a generic function, that doesn't work.
You could do something like this
class Test {
func test<T: MyProcotol>(item: T, completion: (Result<T>) -> Void) {
let result : Result<T> = .success(value: item)
completion(result)
}
}
Cannot convert value of type '(Store).Type' to expected argument type 'BindingC'
Case sensitivity matters. You mean store
, the StoreViewModel
instance and not the type of self
. Further the purpose of a ForEach
expression is to iterate an array (presumably item(s)
).
First of all to avoid more confusion rename item
in StoreViewModel
as its plural form
class StoreViewModel: ObservableObject{
@Published var items: [String] = []
@Published var amount: [String] = []
}
Then replace
ForEach((Store), id: \.self){ item in
with
ForEach(store.items, id: \.self){ item in
Swift 4 - Generic Type Conversion issue - Cannot convert to expected type '(_) - Void'
In your f2
, the type of closure
is @escaping (ValueType, @escaping (ValueType2) -> Void) -> Void
.
The type of the first parameter is ValueType
.
But you are using it as:
closure(value!, s1.f2)
The type of the first argument value!
is Value<ValueType>
, not ValueType
.
If you change the type of closure
to @escaping (Value<ValueType>, @escaping (ValueType2) -> Void) -> Void
, your code would compile without any issue.
You may have found some issue about generics, but at least, your code example is not describing the issue.
Related Topics
Swift 2: Multiline Mkpointannotation
Xctest Unit Test Data Response Not Set in Test After Viewdidload
Use of or Operator on Cloudkit Predicate
Disable Email Detection in Swiftui's Text
Replacing Multiple Different Occurences with Multiple Different Replacements - Swift4.2
Stopping Timer at Defined Amount of Time in Swift
Swiftui Tabview Gives an Error Message During Add/Delete the Element of Coredata
How to Make Struct Lazylist in Swiftui
Can't Use 'Shape' as Type in Swiftui
How to Handle Unsafepointer<Unmanaged<Cfarray>>
Render Images on iOS 14 Widgets
Swift Generics and Protocols Not Working on Uikit [Possible Bug]
How to Compare Two Strings to Check If They Have Same Characters Swift 4