3
votes

I have a class that manages positioning of UIKit elements using 'frame':

class EasyPos: UIView {
    var screenWidth = UIScreen.main.bounds.width
    var screenHeight = UIScreen.main.bounds.height

    var x: CGFloat = 0          { didSet { self.updateFrame() } }
    var y: CGFloat = 0          { didSet { self.updateFrame() } }
    var width: CGFloat = 0      { didSet { self.updateFrame() } }
    var height: CGFloat = 0     { didSet { self.updateFrame() } }

    func updateFrame() {
        frame = CGRect(x: x, y: y, width: width, height: height)

        if x < 0 {
            frame = CGRect(x: screenWidth - abs(x) - width, y: frame.minY, width: frame.width, height: frame.height)
        }
        if y < 0 {
            frame = CGRect(x: frame.minX, y: screenHeight - abs(y) - height, width: frame.width, height: frame.height)
        }
    }

    required init(x: CGFloat = 0, y: CGFloat = 0, width: CGFloat = 40, height: CGFloat = 40) {

        self.x = x
        self.y = y
        self.width = width
        self.height = height

        super.init(frame: .zero)

        updateFrame()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Now I want to add one class that inherits from UIbutton and one that inherits from a UILabel. And they should both be able to use the methods from the EasyPos class. How do I do this? (I tried inheritance from two classes, didn't work)

I know it has something to do with protocols. But I couldn't get this to work either.

Thanks for you help ;)

1
create an extension for UIView.. - Harsh

1 Answers

2
votes

One way you could do this is to write a protocol extension. Because you have properties you'll need to implement a component but it shouldn't be too difficult -

struct FrameComponent {
    var x: CGFloat = 0         
    var y: CGFloat = 0          
    var width: CGFloat = 0      
    var height: CGFloat = 0
}

protocol EasyPos {
    var fc: FrameComponent { get, set }
    func updateFrame()
}

extension EasyPos where Self: UIView {
     func updateFrame() {
        frame = CGRect(x: fc.x, y: fc.y, width: fc.width, height: fc.height)

        if fc.x < 0 {
            frame = CGRect(x: screenWidth - abs(fc.x) - fc.width, y: frame.minY, width: 
              frame.width, height: frame.height)
        }
        if fc.y < 0 {
            frame = CGRect(x: frame.minX, y: screenHeight - abs(fc.y) - fc.height, width: 
              frame.width, height: frame.height)
        }
    }
}

Something you should remember is extensions can't add property observers, so you will need to call updateFrame() manually.