Just An Application

August 25, 2015

Swift Miscellany: Parsing With Generics And Protocols

The pseudo-code to parse a parenthesis delimited comma separated list of homogeneous elements, such as this one

    tuple-pattern : '(' tuple-pattern-element-list? ')'
    
    tuple-pattern-element-list : tuple-pattern-element
                               | tuple-pattern-element ',' tuple-pattern-element-list

or this

    parenthesized-expression : '(' expression-element-list? ')'
    
    expression-element-list : expression-element
                            | expression-element ',' expression-element-list

looks something like this

    ...
    
    if next token != '('
    {
        error
    }
    
    initialize element list
    
    while peek token != ')'
    {
        element = try to parse element
        
        add element to element list
    }
    if next token != ')'
    {
        really bad error
    }
    return element list
    
    ...

The differences in each case will be the types of ‘element’ and ‘element list’ and exactly what is involved in parsing the element.

The number of times you get to write the actual code in practice will depend to a large extent on the programming language you are using.

Since Swift supports generics we should be able to get away with writing the actual code just once.

We can define a function with a signature something like this

    func list<T>(tokens:TokenStream, 'something to parse the element of type T') -> [T]?

One choice for the ‘something to parse the element of type T’ is another function.

The function is passed the tokens and it returns an instance of type T or nil if there was an error which gives us the signature

    (tokens:TokenStream) -> T?

which in turn gives us the function

    func list(tokens:TokenStream, parser:(tokens:TokenStream) -> T?)  -> [T]?
    {
        if !next(tokens, .LEFT_PAREN)
        {
            return nil
        }
    
        var elements = [T]()
    
        while !peek(tokens, .RIGHT_PAREN)
        {
            let element = parser(tokens:tokens)
    
            if element == nil
            {
                return nil
            }
    
            elements.append(element!)
    
            if !peek(tokens, .COMMA)
            {
                break
            }
            assertNext(tokens, .COMMA)
        }
        assertNext(tokens, .RIGHT_PAREN)
        return elements
    }

In Swift 2.0 we can make things simpler by dispensing with the returning nil on error convention.

    func list(tokens:TokenStream, parser:(tokens:TokenStream) throws -> T) throws  -> [T]
    {
        try next(tokens, .LEFT_PAREN)
    
        var elements = [T]()
    
        while !peek(tokens, .RIGHT_PAREN)
        {
            elements.append(try parser(tokens:tokens))
    
            if !peek(tokens, .COMMA)
            {
                break
            }
            assertNext(tokens, .COMMA)
        }
        assertNext(tokens, .RIGHT_PAREN)
        return elements
    }

Taking A Slightly More Object-oriented Approach

For practical or ideological reasons we might want to use an ‘object’ or ‘objects’ to do the parsing rather than functions.

In this case we might want to pass an instance of a type capable of doing the parsing of the element rather than using one these old-fangled closure thingys.

For the method, as it now is, to remain generic one possibility would be to pass an instance of a generic class in which case the function signature would look something like this

    func list<T>(parser:GenericListElementParser<T>) throws -> [T]

This is pretty straightforward but not that flexible.

The original function could take any function, method, or closure with the right signature, but in this case any object passed would either have to an instance of the generic class itself or a sub-class of it.

It might be better if we could define a protocol which the object must implement but there seems to be a problem.

    protocol ListElementParser
    {
        func parse() throws -> ????
    }

How do we define the return type of the method the object must implement ?

Unlike classes, enums and structs, protocol definitions cannot have a generic argument clause so how do we define the return type ?

The answer is to define an ‘associated type’ that can then be referenced in subsequent declarations in the protocol

    protocol ListElementParser
    {
        typealias ElementType
        
        func parse() throws -> ElementType
    }

For each type that implements the protocol ListElementParser, for example

    final class ExpressionElementParser: ListElementParser
    {
        func parse() throws -> ExpressionElement
        {
            ...
        }
    }

the concrete type corresponding to ElementType is inferred from the declaration of the parse method.

The function signature now has to be generic in the argument type and the return type but what does the constraint look like ?

    func list<????>(parser:P) throws -> T

It has to include both P and T, and we have to constrain the type P to implement the ListElementParser.

The constraint on the the type P can be expressed like this

    P:ListElementParser

so how about

    func list<P:ListElementParser, T>(p:P) throws -> [T]
    {
        try next(.LEFT_PAREN)
    
        var elements = [T]()
    
        while !peek(.RIGHT_PAREN)
        {
            elements.append(try p.parse())
    
            if !peek(.COMMA)
            {
                break
            }
            assertNext(.COMMA)
        }
        assertNext(.RIGHT_PAREN)
        return elements
    }

Nope, the compiler is having none of it.

It states, not unreasonably

    Cannot invoke 'append' with an argument list of type '(P.ElementType)'

Just plonking the T in the generic argument list tells the compiler nothing.

We have to relate the type T to the type ElementType being returned from the call to the parse method.

Fortunately there is a place in the generic parameter list where we can put requirements like this.

The requirement we have is that

the type ElementType of the ListElementParser type is the same as the type T

which in generic parameter clause requirements speak can be expressed very simply

    P.ElementType == T

We can add this to the generic parameter clause in the ‘requirements section’ and the compiler is happy.

    func list<P:ListElementParser, T where P.ElementType == T>(p:P) throws -> [T]
    {
        try next(.LEFT_PAREN)
    
        var elements = [T]()
    
        while !peek(.RIGHT_PAREN)
        {
            elements.append(try p.parse())
    
            if !peek(.COMMA)
            {
                break
            }
            assertNext(.COMMA)
        }
        assertNext(.RIGHT_PAREN)
        return elements
    }

An Incremental Improvement

To use the function we need to first construct an instance of the parser which is a pain if the only reason for constructing it is to pass it to the function.

Why can’t the function construct the parser itself ?

In Swift it can.

We need to change the function signature to take a type which implements ListElementParser.

    func list<P:ListElementParser, T where P.ElementType == T>(pType:P.Type) throws -> [T]

and we need to specify that the type implements the necessary constructor.

    protocol ListElementParser
    {
        typealias ElementType
    
        init(context:ParserContext, tokens:TokenStream)
    
        func parse() throws -> ElementType
    }

To construct an instance we simply do

    let parser = pType.init(context:context, tokens:tokens)

The function now looks like this

    func list<P:ListElementParser, T where P.ElementType == T>(pType:P.Type) throws -> [T]
    {
        try next(.LEFT_PAREN)
    
        let parser   = pType.init(context:context, tokens:tokens)
        var elements = [T]()
    
        while !peek(.RIGHT_PAREN)
        {
            elements.append(try parser.parse())
    
            if !peek(.COMMA)
            {
                break
            }
            assertNext(.COMMA)
        }
        assertNext(.RIGHT_PAREN)
        return elements
    }

To invoke the method we now pass the type of the parser

    try list(ExpressionElementParser.self)

Another Incremental Improvement

Now it is no longer necessary to contruct an instance of the parser for type T but it is still necessary to know what the type of parser is.

It would be simpler if it was possible to simply pass the type of T and decouple the caller from the details of how T‘s get parsed.

We can also do this.

To do so we need another protocol.

    protocol ListElement
    {
        typealias ParserType: ListElementParser
    
        static var parserType : ParserType.Type { get }
    }

and the method now looks like this

    func list<T:ListElement where T.ParserType.ElementType == T>(tType:T.Type) throws -> [T]
    {
        try next(.LEFT_PAREN)
            
        let parser   = tType.parserType.init(context:context, tokens:tokens)
        var elements = [T]()
            
        while !peek(.RIGHT_PAREN)
        {
            elements.append(try parser.parse())
            
            if !peek(.COMMA)
            {
                break
            }
            assertNext(.COMMA)
        }
        assertNext(.RIGHT_PAREN)
        return elements
    }

For this to work in the ExpressionElementParser case the ExpressionElement type has to implement the ListElement protocol.

    enum ExpressionElement: ListElement
    {
        static let parserType = ExpressionElementParser.self
    
        //
    
        case EXPRESSION(Expression)
        case NAMED_EXPRESSION(String, Expression)
    }

Now we can simply pass the type of the elements in the list.

    try list(ExpressionElement.self)

Via the extension mechanism this approach can be made to work with any class, enum, or struct type.

Defining

    final class StringListElementParser: ListElementParser
    {
        init(context:ParserContext, tokens:TokenStream)
        {
            // ...
        }
    
        func parse() throws -> String
        {
            // ...
        }
    }

and

    extension String: ListElement
    {
        static let parserType = StringListElementParser.self
    }

means we can do

    try list(String.self)

Copyright (c) 2015 By Simon Lewis. All Rights Reserved.

Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.

Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.

August 24, 2015

Drawing Triangles For Fun And Profit, Or How To Make Your Popovers Stand Out From The Crowd

Filed under: iOS, Swift, UIKIt, UIPopoverBackgroundView — Tags: , , , — Simon Lewis @ 11:02 am

If have you have ever wanted to make the arrows of your popovers that little bit more ‘pointy’, or you have hankered after a co-respondent popover, for example

Popover

then help is at hand courtesy of the UIPopoverBackgroundView class.

The UIPopoverBackgroundView Class

The UIPopoverBackgroundView class defines two properties.

The arrowDirection Property

    var arrowDirection: UIPopoverArrowDirection

The documentation for this reads

The direction in which the popover arrow is pointing.

which is entirely obvious unless it is not.

A picture sometimes helps.

Arrows And Their Directions

UpDownLeftRight

The arrowOffset Property

    var arrowOffset: CGFloat

The documentation uses a lot of words to explain this.

Here are some pictures instead

Offset For Vertical Arrows

VerticalOffsets

Offset For Horizontal Arrows

HorizontalOffsets

The UIPopoverBackgroundViewMethods Protocol

The UIPopoverBackgroundView class implements the UIPopoverBackgroundViewMethods protocol

The arrowBase Method

    static func arrowBase() -> CGFloat

Note that this is a static, i.e., class method

The base of an arrow (see below) must be the same for all directions and it must not change.

The arrowHeight Method

    static func arrowHeight() -> CGFloat

Note that this is a static, i.e., class method

The height of an arrow (see below) must be the same for all directions and it must not change.

The contentViewInsets Method

    static func contentViewInsets() -> UIEdgeInsets

Note that this is a static, i.e., class method

This method specifies the distances between the edges of the popover’s content and the edges of the background view’s frame. exclusive of the arrow.

Arrow Bases And Heights

BaseHeight

Subclassing The UIPopoverBackgroundView Class

The only way to make use of the UIPopoverBackgroundView class is to sub-class it and override both it properties and the three methods defined by the UIPopoverBackgroundViewMethods protocol.

The arrowDirection Property

It is not possible to override the arrowDirection property with a stored property so we need to define a computed
property.

To start with we don’t really know what we should be doing when getting or setting the value but the pseudo-code looks like this

    override var arrowDirection : UIPopoverArrowDirection
    {
        get
        {
            return ????
        }
    
        set
        {
            ???? = newValue
        }
    }

The arrowOffset Property

The same holds true for the arrowOffset property. It needs to be overridden by a computed property and we don’t really know what we will need to do.

    override var arrowOffset : CGFloat
    {
        get
        {
            return ????
        }
        
        set
        {
            ???? = newValue
        }
    }

The arrowBase Method

This is a ‘class’ method so there is not a lot of room for manoeuvre, We will will need to return some kind of constant value obtained from somewhere.

    override static func arrowBase() -> CGFloat
    {
        return ????
    }

The arrowHeight Method

The same is true for the arrowHeight method.

    override static func arrowHeight() -> CGFloat
    {
        return ????
    }

The contentViewInsets Method

This one we can do straight away

    override static func contentViewInsets() -> UIEdgeInsets
    {
        return UIEdgeInsets(top: 10.0, left: 10.0, bottom:10.0, right: 10.0)
    }

but its really not that exciting.

A Direction Digression Or When Is An Enum Not An Enum ?

For our purposes the arrow direction can be one of

  • Up

  • Down

  • Left

  • Right

This can be represented by the Swift enum

    enum Direction
    {
        case UP
        case DOWN
        case LEFT
        case RIGHT
    }

which results in switch statements that look like this

    switch direction
    {
        case .UP:
    
            ...
            
        case .DOWN:
        
            ...
            
        case .LEFT:
        
            ...
            
        case .RIGHT:
        
            ...
    }

What the API uses to represent the direction of an arrow is the type

    UIPopoverArrowDirection

which results in switch statements that look like this

    switch direction
    {
        case UIPopoverArrowDirection.Up:
    
            ...
    
        case .UIPopoverArrowDirection.Down:
    
            ...
    
        case .UIPopoverArrowDirection.Left:
    
            ...
    
        case .UIPopoverArrowDirection.Right:
    
            ...
            
        default:
        
            ...
    }

because in Swift UIPopoverArrowDirection is not an enum at all.

In Objective-C UIPopoverArrowDirection is defined like this

    typedef NSUInteger UIPopoverArrowDirection;

There are some associated constants defined using an anonymous enum

    enum {
        UIPopoverArrowDirectionUp = 1UL << 0,
        UIPopoverArrowDirectionDown = 1UL << 1,
        UIPopoverArrowDirectionLeft = 1UL << 2,
        UIPopoverArrowDirectionRight = 1UL << 3,
        UIPopoverArrowDirectionAny = UIPopoverArrowDirectionUp | UIPopoverArrowDirectionDown |
        UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionRight,
        UIPopoverArrowDirectionUnknown = NSUIntegerMax
    };

This is a standard ‘C’ idiom which makes it possible to specify both an arrow direction and a set of arrow directions as values of the ‘type’ UIPopoverArrowDirection.

This translates to something like the following in Swift

    struct UIPopoverArrowDirection : RawOptionSetType {
        init(_ rawValue: UInt)
        init(rawValue rawValue: UInt)
        static var Up: UIPopoverArrowDirection { get }
        static var Down: UIPopoverArrowDirection { get }
        static var Left: UIPopoverArrowDirection { get }
        static var Right: UIPopoverArrowDirection { get }
        static var Any: UIPopoverArrowDirection { get }
        static var Unknown: UIPopoverArrowDirection { get }
    }

which provides a bit of syntactic sugar, and a little more type safety in that you cannot accidentally pass any old UInt to something expecting a UIPopoverArrowDirection value. Now you have to wrap it in a struct first !

In our case, semantically at least, the API shouldn’t be passing a value that is not equal to one of the static values Up, Down, Left, or Right but as the compiler is making clear there is nothing to stop it doing so programatically, hence the need for a ‘default’ case.

The problem with having to deal with a default case is that increases the complexity of the code for no gain whatsoever.

Each time we switch on a value of ‘type’ UIPopoverArrowDirection we have to decide what the ‘right thing’ to do is in the default case, even if that thing is nothing.

If we change the code containing the switch then the decision needs to be taken once again.

If we need to add another switch you need to make the decision again.

Its much easier and safer to work with values of type Direction internally, converting from the UIPopoverArrowDirection value at the point it is set and converting back again when the value is accessed

We can extend Direction quite simply to do the conversions for us

    extension Direction
    {
        static func fromPopoverArrowDirection(direction:UIPopoverArrowDirection) -> Direction?
        {
            switch direction
            {
                case UIPopoverArrowDirection.Up:
    
                    return .UP
    
                case UIPopoverArrowDirection.Down:
    
                    return .DOWN
    
                case UIPopoverArrowDirection.Left:
    
                    return .LEFT
    
                case UIPopoverArrowDirection.Right:
    
                    return .RIGHT
    
                default:
    
                    return nil
            }
        }
    
        func toPopoverArrowDirection() -> UIPopoverArrowDirection
        {
            switch self
            {
                case .UP:
    
                    return UIPopoverArrowDirection.Up
    
                case .DOWN:
    
                    return UIPopoverArrowDirection.Down
    
                case .LEFT:
    
                    return UIPopoverArrowDirection.Left
    
                case .RIGHT:
    
                    return UIPopoverArrowDirection.Right
            }
        }
    }

We’re Going To Need An ‘Arrow’

So far its been all arrows all the time so let’s define a nifty structure to hold all the arrow related stuff

    private struct Arrow
    {
        let height    : CGFloat   = 30.0
        let base      : CGFloat   = 20.0
    
        var direction : Direction = .UP
        var offset    : CGFloat   = 0.0
    }

a variable for storing one

    private var arrow  : Arrow = Arrow()

and a ‘prototype’ arrow for the static methods to access

    private static let PROTO_ARROW = Arrow()

New And Improved

We can now flesh out the implementations of the overridden methods and properties like so

    override static func arrowBase() -> CGFloat
    {
        return PROTO_ARROW.base
    }
    override static func arrowHeight() -> CGFloat
    {
        return PROTO_ARROW.height
    }

For the arrowDirection property, if we are ever handed an ‘invalid’ UIPopoverArrowDirection value we simply drop it on the floor. Its not clear what else we could do.

    override var arrowDirection : UIPopoverArrowDirection
    {
        get
        {
            return arrow.direction.toPopoverArrowDirection()
        }
    
        set
        {
            if let direction = Direction.fromPopoverArrowDirection(newValue)
            {
                arrow.direction = direction
            }
        }
    }
    override var arrowOffset: CGFloat
    {
        get
        {
            return arrow.offset
        }
    
        set
        {
            arrow.offset = newValue
        }
    }

Now What ?

Now we have to provide the ‘background’ for the popover.

By default the background is simply an arrow plus a rectangle.

In theory we could draw it but the documentation states that we should use images.

To do this we need to add two instances of UIImageView as subviews, one for the arrow and one for the ‘rest’

BasicBackground

The basic task is to work out where the two components of the background should go.

We need to set the frames of the two subviews on the basis of the arrow base and height, and the current values for the arrow’s direction and offset.

We can define a method on the Arrow struct which returns its frame given the bounds of its super view

    func frame(container:CGRect) -> CGRect
    {
        let containerMidX   = CGRectGetMidX(container)
        let containerMidY   = CGRectGetMidY(container)
        let containerWidth  = container.size.width
        let containerHeight = container.size.height
    
        let halfBase        = base/2.0
    
        let x    : CGFloat
        let y    : CGFloat
        let size : CGSize = frameSize()
    
        switch direction
        {
            case .UP:
    
                x = containerMidX + offset - halfBase
                y = 0.0
    
            case .DOWN:
    
                x = containerMidX + offset - halfBase
                y = containerHeight - height
    
            case .LEFT:
    
                x = 0.0
                y = containerMidY + offset - halfBase
    
            case .RIGHT:
    
                x = containerWidth - height
                y = containerMidY + offset - halfBase
        }
        return CGRect(x: x, y: y, width:size.width, height:size.height)
    }

When the arrow is ‘vertical’ the x coordinate of the origin is the same, and the arrow is either at the ‘top’ if the direction is .UP, or at the bottom if the direction is .DOWN.

When the arrow is ‘horizontal’ the y coordinate of the origin is the same and the arrow is on the left if the direction is .LEFT or on the right if the direction is .RIGHT.

This method calls the frameSize method

    private func frameSize() -> CGSize
    {
        switch direction
        {
            case .UP,
                 .DOWN:
    
                return CGSize(width: base, height: height)
    
            case .LEFT,
                 .RIGHT:
    
                return CGSize(width: height, height: base)
        }
    }

Since the layout is a function of the current values of the arrow’s direction and offset we need to add calls to the setNeedLayout method each time either of these values change.

    override var arrowDirection : UIPopoverArrowDirection
    {
        get
        {
            return arrow.direction.toPopoverArrowDirection()
        }
    
        set
        {
            if let direction = Direction.fromPopoverArrowDirection(newValue)
            {
                arrow.direction = direction
                setNeedsLayout()
            }
        }
    }
    override var arrowOffset: CGFloat
    {
        get
        {
            return arrow.offset
        }
    
        set
        {
            arrow.offset = newValue
            setNeedsLayout()
        }
    }

This ensures that the layoutSubviews method will be called when necessary.

    override func layoutSubviews()
    {
        let arrowFrame      = arrow.frame(self.bounds)
        var backgroundFrame = self.bounds
    
        switch arrow.direction
        {
            case .UP:
    
                backgroundFrame.origin.y    += arrowFrame.height
                backgroundFrame.size.height -= arrowFrame.height
    
            case .DOWN:
    
                backgroundFrame.size.height -= arrowFrame.height
    
            case .LEFT:
    
                backgroundFrame.origin.x   += arrowFrame.width
                backgroundFrame.size.width -= arrowFrame.width
    
            case .RIGHT:
    
                backgroundFrame.size.width -= arrowFrame.width
        }
    
        backgroundView?.frame = backgroundFrame
    
        arrowView?.image = arrowImages[arrow.direction]
        arrowView?.frame = arrowFrame
    }

Wiring It All Up

To get our UIPopoverBackgroundView sub-class to be used for a popover being presented via a segue we need to set the property

   var popoverBackgroundViewClass: AnyObject.Type?

of the UIPopoverPresentationController instance, managing the popover’s display.

This can be done in the appropriate prepareForSegue method

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
    {
        if let segueId = segue.identifier
        {
            switch segueId
            {
                case "CustomPopoverSegue":
    
                    let dvc = segue.destinationViewController as? UIViewController
                    let ppc = dvc?.popoverPresentationController
    
                    ppc?.popoverBackgroundViewClass = CustomPopoverBackgroundView.self
    
                default:
    
                    break
            }
        }
    }

Note that it is the class itself not an instance of the class which is assigned to the property.

About That Arrow Drawing …

It turns out that no actual drawing of arrows is required at runtime which is a bit disappointing.

This is not strictly true, you can draw them, it does appear to work, but you are supposed to use images.

You can, if you wish, use a single image and rotate it as necessary.

Alternatively, for those of us who do not entirely trust affine transformations, after all how do you know what they are really doing ?, you simply have one image for each direction, which you can of course draw, so all is not lost.

Here’s some very simple code for drawing a triangle on Mac OS X.

    func drawArrow(width:Int, height:Int, vertices:(CGPoint, CGPoint, CGPoint), colour:NSColor) -> NSData?
    {
        let bitmap = NSBitmapImageRep(
                         bitmapDataPlanes:
                             nil,
                         pixelsWide:
                             width,
                         pixelsHigh:
                             height,
                         bitsPerSample:
                             8,
                         samplesPerPixel:
                             4,
                         hasAlpha:
                             true,
                         isPlanar:
                             false,
                         colorSpaceName:
                             NSCalibratedRGBColorSpace,
                         bytesPerRow:
                             (4 * width),
                         bitsPerPixel:
                             32)
        
        NSGraphicsContext.saveGraphicsState()
        NSGraphicsContext.setCurrentContext(NSGraphicsContext(bitmapImageRep:bitmap!))
        
        let (v0, v1, v2) = vertices
        
        let path = NSBezierPath()
        
        path.moveToPoint(v0)
        path.lineToPoint(v1)
        path.lineToPoint(v2)
        path.lineToPoint(v0)
        path.closePath()
        
        colour.setFill()
        
        path.fill()
        
        NSGraphicsContext.restoreGraphicsState()
        
        return bitmap?.representationUsingType(.NSPNGFileType, properties: [NSObject: AnyObject]())
    }

Copyright (c) 2015 By Simon Lewis. All Rights Reserved.

Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.

Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.

Create a free website or blog at WordPress.com.

%d bloggers like this: