Realmswift Initialize List:Cannot Specialize a Non-Generic Definition

RealmSwift initialize list : Cannot specialize a non-generic definition

I wanted to give the solution to this question some context. In Swift, namespacing is implicit on a module level. If you have external modules, such as RealmSwift, which has a type List you can still have a type named List in your own module. You can even have multiple external modules with the type List.

My reasoning for the error you presented was as follows

  1. In Realm, what you posted is exactly how you're supposed to declare a list
  2. Your example compiled in the context of my project which already uses Realm Lists
  3. The error indicated suggests that the swift compiler knows that List is a valid type and in fact knows about a function named List.init(), however, the compiler is telling you that the function isn't generic.

The only answer at that point, is to assume the compiler is using a different definition of List than you are intending. The only way this happens is if the scope you're in (your project or another type), has also defined a type List, since internal types take precedence over external types. This precedence is extended further with type nesting. If you'd like to keep Realm's List as the default list, you can nest your List in another structure to provide a namespace of sorts.

The following example is as concise as possible given the complex situation.

import RealmSwift

let myGlobalDogs = List()
let myGlobalNestedListDogs = MyClass.List()
let globalDogs = RealmSwift.List<Dog>()

class List { }

class MyClass {
class List { }

let dogs = RealmSwift.List<Dog>()
let myNestedListDogs = List() // type: MyModule.MyClass.List
let myDogs = MyModule.List() // type: MyModule.List
}

class MyOtherClass {

let dogs = RealmSwift.List<Dog>()
let myNestedListDogs = MyClass.List() // type: MyModule.MyClass.List
let myDogs = List() // type: MyModule.List
}

Fortunately, types/functions are usually different enough that you can't inadvertently use the wrong one without encountering an error eventually, such as the one you encountered.

Similar types: Cannot specialize a non-generic definition

In order for the compiler to be able to decide which Property element you want to use, you have to add the namespace. In this case:

  • Realm.Property to use the Property element from Realm
  • ReactiveSwift.Property to use the Property element from ReactiveSwift

Create array of other model with Realm - SwiftUI

First you want to leverage a List object instead of an array to store players in a team:

class Team: Object{
@objc dynamic var teamName: String = ""
let playerList = List<Player>()
}

that will create a one to many relationship (one team has many players).

If you need to traverse from player back to team you can either manually do it with a direct relationship

class Player: Object{
@objc dynamic var playerName: String = ""
@objc dynamic var shirtNumber: Int = 0
@objc dynamic var myTeam: Team!
}

or you can have Realm manage it for you and automatically create the inverse relationship*

class Player: Object{
@objc dynamic var playerName: String = ""
@objc dynamic var shirtNumber: Int = 0
var teams = LinkingObjects(fromType: Team.self, property: "playerList")
}

As far as iterating over the teams and players, just a simple for loop will do it

let teamResults = realm.objects(Team.self)

for team in teamResults {
print(team.teamName)
for player in team.playerList {
print(" player: \(player.playerName)"
}
}

*note that LinkingObjects is plural. It actually creates a many to many relationship - that means a player could be linked back to several teams. This generally isn't an issue and more a design choice.

How to persist a Realm List property in Swift 4?

Realm Lists can never be nil, and they don’t need the @objc dynamic. They should only be let, although I can't find that specifically called out in the documentation, there is a comment from a realm contributor that calls it out specifically

There is a cheat sheet for properties in the documentation.

let dogs = List<Dog>()

Swift: Realm generic function with T like kotlin

First, change method declaration to current Swift syntax

func get<T: Object>(completion: ([T]) -> Void) {
// ...
}

Next, compiler can infer type of T if you specify this type in closure of get method

get { (customers: [Customer]) -> Void in
// ... work with `customers`
}

so then you can use in method just

let results: Results<T>

Define a Swift typealias for any object that implements multiple protocols

The code that you posted has a different meaning from what you'd expect. You're treating AnyObject like a generic type, with UIPickerViewDataSource and UIPickerViewDelegate as type arguments. It's the same thing as creating a Dictionary with Int keys and String values, for example:

var someDictionary: Dictionary<Int, String>

What you're trying to accomplish needs a different construct, called protocol composition. Swift provides it specifically to express types that conforms to multiple protocols. Its syntax is the following, you can use it anywhere you can use regular types:

FirstProtocol & SecondProtocol

Using this feature, your code would become:

// The typealias definition
typealias CellDelegate = UIPickerViewDataSource & UIPickerViewDelegate

// In my UITableViewCell subclass:
weak var delegate: CellDelegate?

Protocol composition is explained in Apple's guide to the Swift language, here.

EDIT: Updated to Swift 3 syntax, thanks @raginmari

Simpler method for decoding JSON from multiple services in Swift

Rather than trying to solve this with CodingKeys and an increasingly complicated init, I suggest composing it via a protocol:

protocol PersonLoader: Decodable {
var name: String { get }
// additional properties
}

extension Person {
init(loader: PersonLoader) {
self.name = loader.name
// additional properties, but this is one-time
}
}

Alternately, particularly if Person is a read-only simple data object, you could just make Person a protocol, and then you could avoid this extra copying step.

You can then define the interfaces for each service independently:

struct Service1Person: PersonLoader {
let name: String
}

struct Service2Person: PersonLoader {
let person_name: String

var name: String { person_name }
}

And then map into Persons when you're done:

let service2Persons = try decoder.decode([Service2Person].self,
from: service2JSONResponse)
.map(Person.init)

If you went with a protocol-only approach, it would look like this instead:

protocol Person: Decodable {
var name: String { get }
// additional properties
}

struct Service1Person: Person {
let name: String
}

struct Service2Person: Person {
var name: String { person_name }
let person_name: String
}

let service2Personsx = try decoder.decode([Service2Person].self,
from: service2JSONResponse) as [Person]

How to test whether generic variable is of type AnyObject

In Swift 3, everything is bridgeable to AnyObject due to the introduction of _SwiftValue (see this Q&A for more info), that can wrap anything that isn't directly bridgeable to Objective-C in an opaque Objective-C compatible box.

Therefore is AnyObject will always be true, as anything can be represented as an AnyObject via wrapping in a _SwiftValue.

One way to check whether a value is a reference type (as shown in this Q&A) is to type-check the type of the value against the metatype of AnyObject, AnyClass (aka AnyObject.Type).

For generics, if you want to check whether the static type of T is a reference type, you can do:

isObject = T.self is AnyClass

If you want to check whether the dynamic type of a value typed as T is a reference type (such as val in your example), you can use the type(of:) function on the unwrapped value, as the aforementioned Q&A suggests:

if let val = val {
isObject = type(of: val) is AnyClass

// ...
}

The difference between these two approaches is that when T is of type Any (or a non AnyObject abstract type), T.self is AnyClass will return false (which could be useful if you want a box where the value could be a reference or value type) – type(of: val) is AnyClass however, will return whether val itself is a reference type.



Related Topics



Leave a reply



Submit