Swift can't infer generic type when generic type is being passed through a parameter
My suggestion is a bit different. It uses static methods
Call loadFromDB
and fetch
on the NSManagedObject
subclass. The benefit is that always the associated type is returned without any further type cast.
Another change is throw
ing errors. As the Core Data API relies widely on throw
ing errors my suggestion is to drop CoreDataResult<Value>
. All errors are passed through. On success the object is returned, on failure an error is thrown.
I left out the id
related code and the update
method. You can add a static func predicate(for id : ID)
protocol CoreDataWriteManagerProtocol {
associatedtype ManagedObject : NSManagedObject = Self
static var persistentContainer : NSPersistentContainer { get }
static var entityName : String { get }
static func loadFromDB(predicate: NSPredicate?) throws -> ManagedObject
static func fetch(request: NSFetchRequest<ManagedObject>) throws -> ManagedObject
static func insertNewObject() -> ManagedObject
}
extension CoreDataWriteManagerProtocol where Self : NSManagedObject {
static var persistentContainer : NSPersistentContainer {
return (UIApplication.delegate as! AppDelegate).persistentContainer
}
static var entityName : String {
return String(describing:self)
}
static func loadFromDB(predicate: NSPredicate?) throws -> ManagedObject {
let request = NSFetchRequest<ManagedObject>(entityName: entityName)
request.predicate = predicate
return try fetch(request: request)
}
static func fetch(request: NSFetchRequest<ManagedObject>) throws -> ManagedObject {
guard let results = try? persistentContainer.viewContext.fetch(request) else {
throw CoreDataResponseError.fetch(entityName: entityName)
}
if let result = results.first {
return result
} else {
throw CoreDataResponseError.idDoesNotExist
}
}
static func insertNewObject() -> ManagedObject {
return NSEntityDescription.insertNewObject(forEntityName: entityName, into: persistentContainer.viewContext) as! ManagedObject
}
}
Swift couldn't infer generic type when I was trying to provide my own implementation of AnySequence
The problem with the first implementation is that
let sequence = CustomAnySequence([1, 2, 3])
does not satisfy the constraint in
init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator
[1, 2, 3]
is a sequence, but its iterator type is not your CustomAnyIterator
. What you really want is to pass a sequence with the same element type, not the same iterator type:
init<S: Sequence>(_ sequence: S) where S.Element == Element
and pass sequence.makeIterator()
to the init method of CustomAnyIterator
.
Note also the inner class can inherit the Element
type placeholder from the outer class, and that the type aliases are not really needed.
final class CustomAnySequence<Element>: Sequence {
class CustomAnyIterator: IteratorProtocol {
private let _next: () -> Element?
init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}
func next() -> Element? {
return _next()
}
}
private let _makeIterator: () -> CustomAnyIterator
init<S: Sequence>(_ sequence: S) where S.Element == Element {
_makeIterator = { CustomAnyIterator(sequence.makeIterator()) }
}
func makeIterator() -> CustomAnyIterator {
return _makeIterator()
}
}
You may also consider to use a struct
instead of a class
.
Swift Generics Generic parameter could not be inferred
It's not possible to implement this correctly. What type is Ztar? How would the compiler know? You've written "fetchData
will fetch some kind of data, out of all the infinitely possible kinds of data in the universe, and you, the compiler, should decode it." That's not possible.
Instead, the way this would generally be written is:
fetchData<T: Codable>(ofType: T.Type, completion: @escaping (Result<T, NetworkError>) -> Void)
And then you would need to pass the type you expect as the first parameter:
fetchData(ofType: Record.self) { resultRecord in ... }
If you don't know what type Ztar is, how can the compiler?
(Note that you should almost never use (T?, Error?)
as a type. That says "maybe T, maybe Error, maybe neither, maybe both." You almost always mean Result<T, Error>
instead. That says "either T or Error.")
Generic parameter 'T' could not be inferred when passing Codable struct
Consider that the parameter in the closure is an instance, not a type. For example like
networkManager.getType(urlString: kGetMyDayTaskDetails + strId,
header: header) { details in
}
To specify the generic type annotate it and according to the signature it must be optional
networkManager.getType(urlString: kGetMyDayTaskDetails + strId,
header: header) { (details : MyDayAndTaskDetails?) in
}
Infer Generic Type In Completion Block
You have explicitly declare the type of result
in the completion handler when you call the function:
MyClass.requestArray() { (result: Result<[String], Error>) in
switch result {
case .success(let array):
break
case .failure(let error):
break
}
}
Generic parameter 'T' could not be inferred after assignment
This may or may not be a compiler bug.
It is known that Swift does not try to infer the types of some closures, namely, multi-statement ones, as said in SR-1570:
This is correct behavior: Swift does not infer parameter or return types from the bodies of multi-statement closures.
However, your closure consists of only one statement, one declaration to be specific. It is possible, albeit weird, that they designed it so that Swift doesn't try to infer types if the closure contains one declaration as well. For example, this does not compile either
f { let x: Int = $0 } // nothing to do with "g"! The issue seems to be with declarations
If this were by-design, the rationale behind it might be because a single declaration in a closure doesn't make much sense anyway. Whatever is declared, won't be used.
But again, this is just speculation, and this could be a bug as well.
To fix it, simply make it a not-a-declaration:
f { _ = g($0) } // this, without the "let", is IMO the idiomatic way to ignore the function result
Or
f { g($0) } // g has @discardableResult anyway, so you don't even need the wildcard
Type inference with Generics in Swift
If you add a type annotation to the closure parameter then
the compiler can infer the generic type T
:
self.getMeGoodies("chocolatechip", callback: { (goodie : Goodie) -> () in
println("eat the \(goodie)")
})
Another method is to pass the type as an argument to the method:
func getMeGoodies<T>(type : T.Type, goodieName : String, callback:(goodie:T) -> ()) {
var goodie:T = 0 //get it from the jug
callback(goodie: goodie)
}
self.getMeGoodies(Goodie.self, goodieName: "chocolatechip", callback: { (goodie) in
println("eat the \(goodie)")
})
Set default or nil value to the generic type parameter of the function
nil
is too broad in this case, as the compiler can't infer to which [T]?
it should apply the nil.
You will need to explicitly specify the Optional
generic argument here:
self.genericCall(param: [StructOne]?.none)
Generic parameter 'T' could not be inferred with closures
You need to explicitly tell the type when calling the function. If you are expecting String then call it with String type.
MyClass.myFunction { (response: String) in
}
Related Topics
Swift - Reorder Uitableview Cells
How to Make Cells Have a Gradient Background
How to Embed Third Party Framework on Ionic Capacitor Custom Plugin
Getting a Let Value Outside a Function
Cannot Invoke 'Filter' with an Argument List of Type '((_) -> _)'
How to Use a Variadic Closure in Swift
Calling a Function Defined in Assembly from Swift
Converting Url to String and Back Again
Pagination with Firebase Firestore - Swift 4
How to Reset Intent Extension Configurations in Widgetkit
iOS 13: Threading Violation: Expected the Main Thread
Avcapturevideodataoutput Captureoutput Not Being Called
Animating a Navigation Bar Color
Define a Swift Protocol Which Requires a Specific Type of Sequence
Binding in a Foreach in Swiftui