[Solved] Member operator ‘%’ must have at least one argument of type ‘ViewController’

I am trying to create a simple Swift 3 template with a custom function for calculating percentage using postfix unary operator in an Xcode app. This may seem like a duplicate question because the accepted answer in my previous post already shows how to do this in Playground. But I have since found that the custom function doesn’t work the same way in an Xcode project.

In the template below, I declared the ’operator' at file scope (or at least I believe I did). But when the postfix function is declared, Xcode advises that

    Operator '%' declared in type 'ViewController' must be 'static' 

and offers a fix-it to insert static. With static inserted Xcode then advises

    Member operator '%' must have at least one argument of type 'ViewController’.

Can anyone explain why the % function needs to be static in the Xcode project and what the last error message means in the context of the same line (see below) ? Thanks

Draft Template

import UIKit

postfix operator %

class ViewController: UIViewController {

var percentage = Double()

override func viewDidLoad() {
    super.viewDidLoad()

    percentage = 25%
    print(percentage)
    }

static postfix func % (percentage: Int) -> Double {
    return (Double(percentage) / 100)
    }
}

EDITED Template

Here’s the working template based on the accepted answer. I hadn’t understood what is meant by declaring the operator at file scope.

import UIKit


postfix operator %

postfix func % (percentage: Int) -> Double {
return (Double(percentage) / 100)
}


class ViewController: UIViewController {

var percentage = Double()

override func viewDidLoad() {
    super.viewDidLoad()

    percentage = 25%
    print(percentage)
    }
}

FOOTNOTE

Building on the accepted answer, custom operator functions grouped in a single file may now be accessed from other files in the same project. To see more visit here.

Enquirer: Greg

||

Solution #1:

I declared the ’operator’ at file scope

No, you didn’t. You defined it in the scope of the
UIViewController definition:

postfix operator %

class ViewController: UIViewController {

    // ...

    static postfix func % (percentage: Int) -> Double {
        return (Double(percentage) / 100)
    }
}

One can define operators as static member functions of a type in Swift 3,
but only if they take at least one argument of that type.

Move the declaration to the file scope to fix the problem:

postfix operator %

postfix func % (percentage: Int) -> Double {
    return (Double(percentage) / 100)
}

class ViewController: UIViewController {

    // ...

}
Respondent: Martin R

Solution #2:

other alternative if you want to use closures in Swift 3:

import UIKit

typealias Filter = (CIImage) -> CIImage

infix operator >>>
func >>> (filter1: @escaping Filter, filter2: @escaping Filter) -> Filter{
    return { image in
        filter2( filter1( image))
    }
}

class ViewController: UIViewController {
    //...
}

Eidhof, Chris; Kugler, Florian; Swierstra, Wouter. Functional Swift: Updated for Swift 3 (Kindle Location 542). GbR Florian Kugler & Chris Eidhof. Kindle Edition.

Respondent: gandhimena

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Leave a Reply

Your email address will not be published.