Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 725 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Use a generic class as a custom view in Interface Builder

#1
I have a custom subclass of UIButton:

import UIKit

@IBDesignable
class MyButton: UIButton {

var array : [String]?

}

It is IBDesignable and I have set it as the custom class for one of the buttons in my storyboard. I would like to make it generic so that the array does not have to be one of String objects. So, I tried this:

import UIKit

@IBDesignable
class MyButton<T>: UIButton {

var array : [T]?

}

However, I am unsure how to set this as the class now in IB. I tried putting `MyButton<String>` or `MyButton<Int>`, but Interface Builder just removes the angle brackets portion and gets the following compile error:

Command /Applications/Xcode6-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 254

Is there a way to use a generic custom class, or is it not supported?
Reply

#2
It is possible to use generic `UIView` in `Interface Builder`. Let's say you have:

class A<T>: UIView {}

First you have to inherit your generic view to make it non-generic:

class B: A<String> {}

Go ahead and use B class in `Interface Builder`.

After it you can make `@IBOutlet` connection in your code:

@IBOutlet var b: B

It will produce error, so to get rid of it make it use `UIView` class instead, and downcast it like so:

@IBOutlet var b: UIView

var _b: B {
b as! B
}

Done, now your `_b` variable is type of `B`, and it works.
Reply

#3
I had the same problem as first I wanted to use the following structure :

import UIKit

protocol MyDataObjectProtocol{
var name:String { get}
}

class MyObjectTypeOne:MyDataObjectProtocol{
var name:String { get { return "object1"}}
}

class MyObjectTypeTwo:MyDataObjectProtocol{
var name:String { get { return "object2"}}
}

class SpecializedTableViewControllerOne: GenericTableViewController<MyObjectTypeOne> {
}

class SpecializedTableViewControllerTwo: GenericTableViewController<MyObjectTypeTwo> {
}

class GenericTableViewController<T where T:MyDataObjectProtocol>: UITableViewController {
// some common code I don't want to be duplicated in
// SpecializedTableViewControllerOne and SpecializedTableViewControllerTwo
// and that uses object of type MyDataObjectProtocol.
}

But as explained in the previous answer, this is not possible. So I managed to work it around with the following code :

import UIKit

protocol MyDataObjectProtocol{
var name:String { get}
}

class MyObjectTypeOne:MyDataObjectProtocol{
var name:String { get { return "object1"}}
}

class MyObjectTypeTwo:MyDataObjectProtocol{
var name:String { get { return "object2"}}
}

class SpecializedTableViewControllerOne: GenericTableViewController {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
super.object = MyObjectTypeOne()
}
}

class SpecializedTableViewControllerTwo: GenericTableViewController {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
super.object = MyObjectTypeTwo()
}
}

class GenericTableViewController : UITableViewController {
var object : MyDataObjectProtocol?

@IBOutlet weak var label: UILabel!

override func viewDidLoad() {
label.text = object?.name
}


// some common code I don't want to be duplicated in
// SpecializedTableViewControllerOne and SpecializedTableViewControllerTwo
// and that uses object of type MyDataObjectProtocol.
}

Now my label outlet displays "object1" when I link the `SpecializedTableViewControllerOne` as a custom class of my view controller in the storyboard and "object2" if I link to `SpecializedTableViewControllerTwo`
Reply

#4
Interface Builder "talks" to your code through the ObjC runtime. As such, IB can can access only features of your code that are representable in the ObjC runtime. ObjC doesn't do generics, so there's not a way for IB to tell the runtime which specialization of your generic class to use. (And a Swift generic class can't be instantiated without a specialization, so you get an error trying to instantiate a `MyButton` instead of a `MyButton<WhateverConcreteType>`.)

(You can recognize the ObjC runtime at work in IB when you break other things: Attempting to use a pure Swift class with outlets/actions in a nib/storyboard gives runtime errors about ObjC introspection. Leaving an outlet connected whose corresponding code declaration has changed or gone away gives runtime errors about KVC. Et cetera.)

To ignore the runtime issues and put it in a slightly different way... let's go back to what IB needs to know. Remember that the nib loading system is what instantiates anything in a storyboard at runtime. So even if the parts of your class that take a generic type parameter aren't `@IBInspectable`, the nib still needs to know what specialization of your generic class to load. So, for IB to let you use generic classes for views, IB would have to have a place for you to identify which specialization of your class the nib should use. It doesn't — but that'd make a great [feature request](

[To see links please register here]

).

In the meantime, if it's still helpful for your `MyButton` class to involve some generic storage, perhaps you could look into having `MyButton` reference another class that includes generic storage. (It'd have to do so in such a way that the type of said storage isn't known at compile time, though — otherwise the type parameters of that other class would have to propagate back to `MyButton`.)
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through