Generic Parameter T could not be inferred with optional generic array - arrays

I have a method in my Model class that has signature below:
func parse<T: Codable>(data: Data) throws -> Array<T>?
When I call the method in another class, Facade, I get the
Generic Parameter T could not be inferred
Calling function as below
if let data = data {
do{
let parsedArray = try self.model.parse(data: data);
}
catch{
print(error)
}
gives me the compiler warning on the line where I call the parse function.

You need to explicitly declare the type of the variable you are setting or add another parameter to the parse method and pass the desired type:
let parsedArray: [YourType] = try model.parse(data: data)

Related

How to change type of a property that gets returned from a method

So I have a method useGetAuthorizationWrapper() which returns { data: unknown } but the expected data that I'll get is an array.
So, when I use data.length I'm getting an error. Obviously, I'll get an error because it is of unknown type.
What I need is => I have to change my return type of data to an array. How can I modify it while calling useGetAuthorizationWrapper() method?
For example like this: useGetAuthorizationWrapper<{ data: [] }>(); // its not working
Under the wood useGetAuthorizationWrapper() calls useQuery() from react-query package
I have searched this issue on the web but didn't get a lead.
When receiving an unknown type you need to cast it:
const wrapper = useGetAuthorizationWrapper();
if (Array.isArray(wrapper.data)) { // just to be sure we have an array
const data = wrapper.data as any[]; // cast unknown field
// do your things
} else {
// handle error
}
However, if possible, you can provide types to useQuery:
by specifying the return and error type: https://react-query-v3.tanstack.com/typescript#defining-custom-hooks (v2 and v3)
by typing the function passed to useQuery and benefitting from type inference https://tanstack.com/query/v4/docs/typescript?#type-inference (v4)

Swift complains of undeclared type, but that doesn't seem to be the problem

I am trying to fetch records in Core Data.
func fetchOrg() {
var **internalOrganization** = [InternalOrganizationMO]() //NSManagedClass
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "InternalOrganization")
fetchRequest.returnsObjectsAsFaults = false
do {
let result = try managedObjectContext.fetch(fetchRequest) as **internalOrganization** **////Compiler flags Error here**
} catch {
fatalError("Failed to fetch internal organization \(error)")
}
}
InternalOrganizationMO is a ManagedObject Class corresponding to the object model and it seems clear to me that internalOrganization is declared to be an array of those objects, so the flagged error seems to be off. My understanding is that this is the kind of object that is supposed to be the target of a fetch, but I am definitely on the learning curve here.
Is it that the fetch needs to be targeted at a Type instead of an array--thus, the complaint about my not providing a named type? If that is it, am I simply supposed to provide the ManagedObject? If that is so, how on earth do I determine how many records are returned?
Is this really better than just using the interface to SQLite?
Thanks, sorry for the rant.
You typecast objects as types, not objects as objects.
Example:
let a = b as! [String]
and not:
let a = [String]()
let c = b as! a
Solution #1:
Change NSFetchRequest<NSFetchRequestResult> to specify the type to be explicitly InternalOrganizationMO, like so:
NSFetchRequestResult<InternalOrganizationMO>
This fetchRequest has now the proper associated type InternalOrganizationMO and will be used accordingly to return objects of this type.
You then won't need to typecast result again and the following code should work just fine:
func fetchOrg() {
let fetchRequest = NSFetchRequest<InternalOrganizationMO>(entityName: "InternalOrganization")
do {
let internalOrganization = try managedContext.fetch(fetchRequest)
/*
internalOrganization will be of type [InternalOrganizationMO]
as that is the return type of the fetch now.
*/
//handle internalOrganization here (within the do block)
print(internalOrganization.count)
}
catch {
fatalError("Failed to fetch internal organization \(error)")
}
}
Solution #2:
If you want this method to work even if the fetchRequest try or typecasting fails then you can do this:
func fetchOrg() {
var internalOrganization = [InternalOrganizationMO]()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "InternalOrganization")
do {
internalOrganization = try managedContext.fetch(fetchRequest) as? [InternalOrganizationMO]
/*
You ofcourse wouldn't want the above optional binding to fail but even if it
does, atleast your method can stay consistent and continue with an empty array
*/
}
catch {
fatalError("Failed to fetch internal organization \(error)")
}
//handle internalOrganization here
print(internalOrganization.count)
}
The choice of solution, depends on your design and requirements.

cannot invoke 'append' with an argument list of type '(T)'

Just got this strange error when trying to write a stack with generic type in latest playground.
I really don't understand what's wrong here, can someone explain to me why I got this error?
class MyStack<T> {
var stack1 = [T]()
func push<T>(value: T) {
stack1.append(value) // Error: cannot invoke 'append' with an argument list of type '(T)'
}
}
The class is already generic, no need to make push generic too
class MyStack<T> {
var stack1 = [T]()
func push(value: T) {
stack1.append(value)
}
}
When push is declared as push<T>, the generic parameter overrides the one defined on the class. So, if we were to rename the generic parameters, we'd get
class MyStack<T1> {
var stack1 = [T1]()
func push<T2>(value: T2) {
stack1.append(value) // Error: cannot invoke 'append' with an argument list of type '(T2)'
}
}
presented like this, it makes sense that we cannot push a T2 in [T1].

GLFW callback signature in Swift 3

I'm trying to setup a simple GLFW application in Swift 3. Currently I'm stuck trying to set a callback function.
func setupGLFW() {
...
glfwSetErrorCallback(errorCallback)
...
}
func errorCallback(error: Int32, description: UnsafePointer<Int8>) {
...
}
This worked in Swift 2 but now I get this error:
cannot convert value of type '(Int32, UnsafePointer) -> ()' to expected argument type 'GLFWerrorfun!'
After consulting the section Interacting with C APIs in the documentation, I also tried this signature:
func errorCallback(error: CInt, description: UnsafePointer<CChar>) {
...
}
This leads to the same error.
The C signature for GLFWerrorfun is:
typedef void(* GLFWerrorfun) (int, const char *)
Try with:
func errorCallback(error: Int32, description: UnsafePointer<Int8>?) {
(Please do not miss the ? after UnsafePointer<Int8>.)
In Swift 3, nullable pointer are imported as Optional pointer, so you need ?.
You could have the callback inline where you call glfwSetErrorCallback:
glfwSetErrorCallback { (error, description) in
//
}
Or, use a closure stored in a variable:
let callback: GLFWerrorfun = { (error, description) in
//
}
glfwSetErrorCallback(callback)
You can see how this typedef is bridged to Swift by Option + Left Clicking on the symbol:
In this case I didn't have the actual GLFW headers, so I just dropped the declaration in a Bridging Header. Your generated interface may show more information.

Error with Parse findObjectsInBackgroundWithBlock in Swift

I'm trying to retrive usernames from Parse's Server with findObjectsInBackgroundWithBlock. I want the results to be stored inside a NSArray, but I get an error in the code.
Here's it:
let query: PFQuery = PFUser.query()!
query.orderByAscending("username")
query.whereKey("username", notEqualTo: myUserId as! String)
query.findObjectsInBackgroundWithBlock {(objects:NSArray?, error:NSError?) -> Void in
}
And I'm getting this error:
Cannot convert value of type '(NSArray?, NSError?) -> Void' to expected argument type 'PFQueryArrayResultBlock?'
I know that everything is working when changing 'NSArray?' to '[PFObject]?', but I want to result to be an Array.. How can I solve this?
You need to do the following:
declare this:
var array:NSArray = NSArray()
query.findObjectsInBackgroundWithBlock {(objects:PFObject?, error:NSError?) -> Void in
if error != nil {
print("error")
} else {
if let objects = objects{
for object in objects {
self.append(object)
}
}
}
}
You can't force the conversion in the callback parameters. Your callback needs to respect the type that will be supplied and then your code in the callback can mutate the supplied parameters and store them.

Resources