2

I have an already setup view and want to wrap it in a subclass of UIView.

class ElementView: UIView {
    var selected = false
}

The problem is that I cannot initialize ElementView with the already existing view. Swift doesn't allow assigning to self too.

init(view: UIView) {
    //here I would have to call super.init(coder: NSCoder?) or super.init(frame: CGRect)
    //none of which actually properly initializes the object
}

Any ideas how to implement this? Thanks :)


Clarification:

I will give you the larger context hoping it'd be more clear:

I am implementing a UIScrollView subclass. The scroll view contains an array of UIView objects which are added externally (from the user of the class). In my custom UIScrollView class I want to implement a tap gesture recognizer for each object. That's already done:

let singleTap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
singleTap.cancelsTouchesInView = false
addGestureRecognizer(singleTap)

and the handler:

func handleTap(recognizer: UITapGestureRecognizer) {
    //some code to handle the tap
}

The problem arises when I want to handle the tap, I want to store the previous state of the view (was it tapped before or not) in order to toggle that state when the tap happens. I want to do different stuff to the UIView depending on its state.

recognizer.view returns the view to which the recognizer is attached to, which is what I need. But, this way I have no possibility of implementing a state for the UIView.

That's why I wanted to implement a custom wrapper for UIView which should contain the state information (which is also a problem). That's how I came up to asking this question...

Rikkles
  • 3,372
  • 1
  • 18
  • 24
Jovan Jovanovski
  • 603
  • 8
  • 16
  • Why not `super.init(frame: view.frame.bounds)` ? (maybe it's `view.bounds`, I can't remember. – Undo Jul 24 '14 at 01:13
  • I'm still confused as to what you are trying to do. Why can't you use super.init(frame: <#CGRect#>)? – Epic Byte Jul 24 '14 at 02:13
  • Are you trying to assign self (the ElementView) equal to view (the parameter)? – Epic Byte Jul 24 '14 at 02:17
  • super.init(frame:) only initializes the frame, but not some other important UIView properties like subviews for example. I'm not trying to assign to self since that's impossible in Swift, I want to call some designated initializer from the UIView superclass which would FULLY initialize the ElementView and then just initialize the selected property which won't be even needed to be done explicitly. – Jovan Jovanovski Jul 24 '14 at 10:54

2 Answers2

2

In order to create a custom init for the UIView subclass you have to call the required init for the UIView superclass. Also while creating the custom init you have to send the Frame of the view to the superclass. Upon fulfilling these requirements you are free to pass on any arguments to the newly created init including the tap recognizer info.

Remember, if you are creating any variables - they have to be not nil upon the creation of the instance, thus in variable declaration you have to create some initial argument (for example - 0 for Int, etc.) for the initializer to work. Here is the example code:

var variableOne: Int = 0
var variableTwo: Int = 0

init(variableOne: Int, variableTwo: Int) {
    self.variableOne = variableOne
    self.variableTwo = variableTwo
    super.init(frame: CGRectZero)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}
Alexander Telegin
  • 665
  • 1
  • 7
  • 22
1

It sounds like you are trying to mimic a copy constructor, and it sounds like you are trying to build it in IB. The short answer is what you are doing doesn't make sense. It further sounds like that you wanted your code above to own or assume the identity of the argument view (your reference to not being able to assign to self). If this assumption is correct, your code would make even less sense - you would just need to assign to a variable.

Just create the view class, with the code that you have posted, you do not need to implement a constructor, since you have provided a default value for your selected variable. Your will with then be populated from IB via the coder based constructor.

If you are trying to clone or copy a given view, then refer to "Can UIView be copied"

Community
  • 1
  • 1
Chris Conover
  • 8,889
  • 5
  • 52
  • 68
  • I agree. Don't even try to clone/deepcopy a view hierarchy, it's not the way to go. Extract from your view the parameters that need to change, and code up some versioning control on those parameters alone. – Rikkles Aug 12 '14 at 17:12