0

I have to create a custom UIView which is actually a circle having the same size and appearance which is placed at different positions in a view. I created an extension which works fine for one circle, but I want to use that same function to place the circle at different positions. Here's my extension:

extension UIView{

func helptip(hotSpot: HelpTips, parentView: UIView){
    hotSpot.tag = 1
    hotSpot.userInteractionEnabled = true
    hotSpot.backgroundColor = UIColor.clearColor()
    hotSpot.translatesAutoresizingMaskIntoConstraints = false

    parentView.addSubview(hotSpot)
    hotSpot.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
    UIView.animateWithDuration(4.0, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity:1, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
            //self.hotSpotOne.center.x += self.view.bounds.width
            hotSpot.alpha = 1.0
            hotSpot.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
            hotSpot.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "showPopover"))
            }, completion: nil)

        let horizontalConstraint = NSLayoutConstraint(item: hotSpot, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: -1)
        let verticalConstraint = NSLayoutConstraint(item: hotSpot
            , attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 16)
        let widthConstraint = NSLayoutConstraint(item: hotSpot, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 50)
        let heightConstraint = NSLayoutConstraint(item: hotSpot, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 50)

    parentView.addConstraints([verticalConstraint, horizontalConstraint, widthConstraint, heightConstraint])

}

}

This is how i call the extension:

hotSpotOne.helptip(self.hotSpotOne, parentView: self.view)// first circle

Now what I want to do is something like this:

hotSpotTwo.helptip(self.hotSpotTwo, parentView: self.view) //second circle

my helptips class looks like this:

   class HelpTips: UIView {
var selectedColor: UIColor = UIColor.TRLMHelpTipYellowColor(){
    didSet{
        self.setNeedsDisplay()
    }
}

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func drawRect(rect: CGRect) {
    let context = UIGraphicsGetCurrentContext()
    CGContextSetLineWidth(context, 1)
    CGContextSetStrokeColorWithColor(context, UIColor.TRLMHelpTipStrokeColor().CGColor)
    let circle = CGRectMake(5, 5, 40, 40)
    CGContextAddEllipseInRect(context, circle)
    CGContextStrokePath(context)
    selectedColor.setFill()
    CGContextFillEllipseInRect(context, circle)
}

 }

I want to use the same extension with different constraints for the above circle as it is placed in a different position in the view. Any help is appreciated. Thanks!

pogbamessi
  • 311
  • 3
  • 17
  • What goes wrong now if you just do that? (That is, which values to you want to change on the second call?) – Phillip Mills Oct 01 '15 at 19:53
  • @PhillipMills What my problem is in the extension I need do a check like if hotSpot == hotSpotOne{ // add the following constraints } else if hotSpot == hotSpotTwo{ //add the following constraints } else{ // add the following constraints } – pogbamessi Oct 01 '15 at 19:54
  • Can you have each hotspot own its constraints (or else package them together in a different object) so that the extension can ask the object that's passed in what should be used? – Phillip Mills Oct 02 '15 at 00:30
  • yes I want it that way but don't know how to do it, i want to have each hot spot to have it's own constraints. So that's why I want to perform a check and then add constraints in the extension. I am kinda new to swift. – pogbamessi Oct 02 '15 at 02:57
  • I think part of my problem in analyzing this is that I don't understand why it's a `UIView` extension instead of a function inside the `HelpTips` class. – Phillip Mills Oct 02 '15 at 12:15
  • @PhilipMills Okay so i think i got it all wrong, may be I don't know the right way to do it. I want a circle to appear on several screens at different positions. So the appearance remains the same for all the circles it's just that their positions(i.e constraints change). So I thought of creating an extension that can be used in all controllers. Can you please tell me what's the best way to implement this? – pogbamessi Oct 02 '15 at 18:52
  • @PhillipMills I actually have a class named HelpTips, I have edited my question and pasted the code for my HelpTips class. – pogbamessi Oct 02 '15 at 19:03

1 Answers1

0

My current thought is to add something like the following to your HelpTips class:

var constraintList: [NSLayoutConstraint] = []
func helptip(parentView: UIView){
    self.tag = 1
    self.userInteractionEnabled = true
    self.backgroundColor = UIColor.clearColor()
    self.translatesAutoresizingMaskIntoConstraints = false

    parentView.addSubview(self)
    UIView.animateWithDuration(4.0, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity:1, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
        //self.hotSpotOne.center.x += self.view.bounds.width
        self.alpha = 1.0
        self.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
        self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "showPopover"))
        }, completion: nil)
    if constraintList.count > 3 {
        parentView.addConstraints([constraintList[0], constraintList[1], constraintList[2], constraintList[3]])
    } else {
        print("Must initialize constraints before displaying.")
    }
}

The caller would then be responsible for supplying the constraints and the calling sequence would be:

var hsp1 = HelpTips(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
hsp1.constraintList.append(NSLayoutConstraint(item: hsp1, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: -1))
hsp1.constraintList.append(NSLayoutConstraint(item: hsp1
    , attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 16))
hsp1.constraintList.append(NSLayoutConstraint(item: hsp1, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 50))
hsp1.constraintList.append(NSLayoutConstraint(item: hsp1, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 50))
hsp1.helptip(parentView)

(Better still would be an addConstraint method in the class so that the caller didn't need to access the constraintList array.)

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • @philipMills Okay this is what my initial thought was but still for me it doesn't seem efficient. If there are suppose 5 circles on a screen at different positions then each time I have to add constraints for each circle. See the width and height constraint are same for each circle, only the vertical and horizontal constraints keep on changing. – pogbamessi Oct 02 '15 at 20:27
  • OK, so set the constant ones internally in the object and only update it from the caller for the ones that change. Whatever...my real point is that a `UIView` extension isn't really necessary for a function that only acts on a well-defined object rather than any arbitrary `UIView`. – Phillip Mills Oct 02 '15 at 22:11