If the postfix operator of a custom function is declared at file scope - as in my previous post - there must be a way to access such a function from another Swift 3 file in the same Xcode project.
Apple’s documentation on custom functions states that “New operators are declared at a global level …“ so I can presume the creators of Swift 3 would consider it important for a custom function to be accessed globally. But for a novice in Swift it is not self-evident how I would do this.
Based on code in my previous accepted answer (here) what would I need to do so a custom function can be accessed from another file elsewhere in the project ?
FINAL EDIT
The solution is embarrassingly simple (see accepted answer) and hopefully other Swift novices may also find it useful.
A postfix operator %
is declared globally while an Extension
of Int
reads an Int
variable from another file. Extensions of Double
and CGFloat
as well as Int
are also possible.
CustomOperators.swift
import UIKit
postfix operator %
extension Double {
static postfix func % (n: Double) -> Double {
return Double(n) / 100
}
}
extension Int {
static postfix func % (n: Int) -> Double {
return Double(n) / 100
}
}
extension CGFloat {
static postfix func % (n: CGFloat) -> Double {
return Double(n) / 100
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
let test1: Double = 93.7
let test2: Int = 80
let test3: CGFloat = 70
override func viewDidLoad() {
super.viewDidLoad()
print(test1%) // prints '0.937'
print(test2%) // prints '0.8'
print(test3%) // prints '0.7'
}
}
Thanks marosoiae, and also Martin R and unniversal for your input.
EDIT 2
Martin R’s comments prompted me to try a further example with my custom postfix function defined in Utils
but in file scope rather than as a static postfix function. Utils
becomes an empty class for custom functions all defined in file scope outside the class.
import UIKit
class ViewController: UIViewController {
let value: Int = 25
override func viewDidLoad() {
super.viewDidLoad()
example1()
example2()
}
func example1() {
// 1. call to a function in Utils with an explicit value
// and nothing returned from Utils.
// Note this uses literal postfix syntax i.e. 25%
Utils.25%
// Debug message:
// Type 'Utils' has no member '25'
}
func example2() {
// 2. call to a function in Utils with an argument
// declared in UIViewController and nothing returned from Utils
Utils.(Int: value)%
// Debug message
// Expected member name following '.'
}
}
Utils.swift
now compiles but from debug messages that Xcode reports with both examples, it is clear that the token '%
' is expected immediately following the '.
'.
Even without returning a variable from Utils.swift
, this is obviously not how to call a postfix function in Utils.swift
from a file elsewhere in the project. My question remains: how would I do it ?
EDIT 1
At this point it might help to include some code so I created a class with static functions, following the syntax (as far as possible) used in Unniversal's answer. I decided to try static functions if these help avoid cluttering the global scope with methods that should be owned by a class/struct.
File 1 - Utils
import UIKit
postfix operator %
class Utils {
static func yourFunction(){
//Do your stuff here
}
static func yourFunction1(value: Int) {
print(value)
}
static postfix func % (percentage: Int) -> Double {
return (Double(percentage) / 100)
}
}
The static function %
reports
Member operator '%' must have at least one argument of type 'Utils'
which I’d expect to disappear once an argument is supplied from another file.
The following code shows four ways I tried to supply an argument to static functions in Utils. I ran the project with one example at a time
File 2 - UIViewController
import UIKit
class ViewController: UIViewController {
let value: Int = 25
var percentage = Double()
override func viewDidLoad() {
super.viewDidLoad()
// example1()
// example2()
// example3()
// example4()
}
func example1() {
// 1. call to a function in Utils with no argument and no return (i.e. suggested answer)
Utils.yourfunction()
// Debug messages:
// Type 'Utils' has no member 'yourfunction'
// Did you mean 'yourFunction'?
// Did you mean 'yourFunction1'?
}
func example2() {
// 2. call to a function in Utils with argument and no return
Utils.yourfunction1(Int: Int)
// Debug messages:
// Type 'Utils' has no member 'yourfunction'
// Did you mean 'yourFunction'?
// Did you mean 'yourFunction1'?
}
func example3() {
// 3. call to a function in Utils with argument and returning a value for percentage
Utils.%() {
return Int(percentage)
}
// Debug message:
// Use of unresolved operator '.%'
}
func example4() {
// 4. call to a function in Utils with argument and returning a value for percentage
percentage = Utils.%(Int: value) -> Int {
return Int(percentage)
}
// Debug messages:
// Use of unresolved operator '.%'
// Expected type before '->'
// Expected type after '->'
}
}
As far as I can see, static functions Utils.yourFunction
and Utils.yourFunction1
can’t be accessed from outside Utils, as shown in example 1 and 2. And the postfix operator %
seems to cause Xcode to report Use of unresolved operator ‘.%’
, as shown in example 3 and 4. However these problems might be the way I adapted the syntax used by Unniversal.
Any function declared at file scope will have the implicit scope internal
and will be visible in the rest of the project/module.
I recommend reading the access control guide for more information.
Edit:
I'm still not sure what you're trying to do, but it looks like you are mixing global functions with static methods and custom operators.
If what you want is to declare a custom operator that you can use in any other file in the project, the solution is in the documentation that you linked in your question.
So this is what you need to declare a custom % (as you defined it) for the Int type:
CustomOperators.swift
postfix operator %
extension Int {
static postfix func % (n: Int) -> Double {
return Double(n) / 100
}
}
main.swift
print(90%) //outputs "0.9"
That's all there is to it. You simply declare the operator globally: postfix operator %
and you define the operator function as a static method in a extension on the Int type.
Now you can use your new operator in other files (like I did in main.swift
).
If you want a function to be accessed globally I would recommend to create a class that has static functions. For example
class Utils {
static func yourFunction(){
//Do your stuff here
}
}
To use it :
Utils.yourfunction()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With