Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: How to add a class method in 'String" extension

Tags:

swift

I want to add a class function into extension:

extension String {
     class func test () {
     }
}

I get the error: Class methods are only allowed within classes; use 'static' to declare a static method

Or how should i call " String.test()"

But for NSString

extension NSString {
    class func aaa () {
    }
}

no errors.

If i add static keyword:

extension String {
    static func aaa () {
        self.stringByAppendingString("Hello")
    }
}

Got: Expression resolves to an unused function,

So how should i add a class function also want to use self. method.

EDIT: This works!

extension String {
    static func aaa (path:String) -> String {
        return path.stringByAppendingString("Hello")
    }
}

but about @lan's answer:

mutating func bbb(path: String) {
    self += "world"
}

When i type it appears like this:

String.bbb(&<#String#>)
String.bbb(&"nihao")

Cannot invoke 'bbb' with an argument list of type '(String)'
like image 286
William Hu Avatar asked May 22 '15 02:05

William Hu


2 Answers

Class and static functions are not called on an instance of a class/struct, but on the class/struct itself, so you can't just append a string to a class.

Apple Documentation:

Within the body of a type method, the implicit self property refers to the type itself, rather than an instance of that type.

You can, however, append a string to a variable instance of a String using the mutating keyword:

extension String {
    mutating func aaa() {
        self += "hello"
    }
}

let foo = "a"
foo.aaa() // ERROR: Immutable value of type 'String' only has mutating members named 'aaa'

var bar = "b"
bar.aaa() // "bhello"

If you are trying to use a pointer to a string as a parameter, you can use the inout keyword to alter the inputed string:

extension String {
    static func aaa(inout path: String) {
        path += "Hello"
    }
}

var foo = "someText"
String.aaa(&foo)
foo //someTextHello
like image 109
Ian Avatar answered Nov 16 '22 14:11

Ian


While correct, it's somewhat atypical to see a mutating member added to a String extension as shown in Ian's answer. Strings (and value types in general) are meant to be immutable so the only way to use a mutating method is to declare instances var at the call site. Most of the time in your code you should be using let constants.

As such, it is much more common to extend structs to return new instances. So this is typical:

extension String {
    func appending(_ string: String) -> String {
        return self + string
    }
}

and then at the call site:

let hello = "Hello, "
let helloWorld = hello.appending("World!")

You'll note of course that I'm not using static at all. That's because appending(_:) needs to use the current instance value of the String we're appending to, and class/static do not refer to instances and therefore do not have values.

like image 29
par Avatar answered Nov 16 '22 14:11

par