2

Lets assume i have a protocol to what only classes can confirm, using that i create typealias combined with some class type.

protocol Foo: class {}
typealias FooView = UIView & Foo

I would like to store instances of UIView conforming to this protocol in a weak hash table. So i do:

let hashtable = NSHashTable<FooView>.weakObjects()

But i receive the following error:

'NSHashTable' requires that 'FooView' (aka 'Foo & UIView') be a class type

I understand that NSHashTable only works with reference types, but what i do not get, since UIView is reference type and Foo protocol is also class type, IMHO it should be a valid declaration.

I understand, that i could just create a class like the following:

class FooView: UIView, Foo {}

And than it would probably work, however, that is not a possible solution. Does someone else have an other idea how to use typealias and still store it in a HashTable?

dirtydanee
  • 6,081
  • 2
  • 27
  • 43

2 Answers2

2

The (shortened) definition of NSHashTable looks like this:

class NSHashTable<ObjectType> : NSObject where ObjectType : AnyObject

and the Foo component doesn't comply to the AnyObject requirement (see Protocol doesn't conform to itself?) for more details why protocols don't conform to other protocols).

An solution to this limitation is to use a wrapper class:

class FooViewWrapper {
    let view: FooView

    init(view: FooView) {
        self.view = view
    }
}

let hashtable = NSHashTable<FooViewWrapper>.weakObjects()

or via generics:

class Ref<T>{
    let value: T

    init(_ value: T) {
        self.value = value
    }
}

let hashtable = NSHashTable<Ref<FooView>>.weakObjects()

Wrapping and unwrapping such views would add some extra code, but will work nicely with hash tables.

Cristik
  • 30,989
  • 25
  • 91
  • 127
  • I was aware of this solution as well, but my aim is not to use any helper class. – dirtydanee Jan 29 '19 at 07:54
  • @dirtydanee in that case I don't think there's a solution to the problem, due to the protocol conformance thing that I mentioned in the answer. – Cristik Jan 29 '19 at 07:56
  • after doing some further research, i came to the conclusion, there is no other way. Sad :( – dirtydanee Jan 31 '19 at 08:02
-3

What you can try is to create an extension of the UIView class which conforms to the Foo protocol:

protocol Foo {
    var bar: Int { get }
}

extension UIView: Foo {
    var bar = 4
}

And if you realy need the typealias, you can also create a typealias on the UIView class itself.

Paul Reznik
  • 965
  • 1
  • 6
  • 18