Flovdis
Flovdis

Reputation: 3095

Swift: Cannot Store Unsafe Pointers in Array

I created a small struct to hold version numbers.

Now I searched a compact way to parse the numbers directly into the variables of the struct. I tried to implement it this way:

struct Version {
    var major: Int = 0
    var minor: Int = 0
    var revision: Int = 0

    init(string: String) {
        let components = string.componentsSeparatedByString(".")
        if 1...3 ~= components.count {
            var targets = [&major, &minor, &revision]
            for index in 0...2 {
                var scanner = NSScanner(string: components[index])
                if (!scanner.scanInteger(target[index])) {
                    major = 0
                    minor = 0
                    revision = 0
                    return                    
                }
            }
        }
    }    
}

But I get this error message:

Type '[inout Int]' of variable is not materializable

I do not understand this error. Is there a way to implement it in this way, using a sort of pointers to the member variables?

Update

In the end I did not use unsafe pointers. This was my final implementation:

init(string: String) {
    let components = string.componentsSeparatedByString(".")
    if 1...3 ~= components.count {
        var values = [0, 0, 0]
        for index in 0..<components.count {
            var scanner = NSScanner(string: components[index])
            if (!scanner.scanInteger(&values[index])) {
                return
            }
        }
        major = values[0]
        minor = values[1]
        revision = values[2]
    }
}

Upvotes: 2

Views: 864

Answers (2)

rintaro
rintaro

Reputation: 51911

in-out is not UnsafePointer nor UnsafeMutablePointer, only if the function accepts Unsafe???Pointer<T> family arguments, in-out expression will be passed as corresponding pointer types. see: the docs

try this:

var targets:[Int] = [0,0,0];
for index in 0...2 {
    var scanner = NSScanner(string: components[index])
    if (!scanner.scanInteger(&targets[index])) {
        major = 0
        minor = 0
        revision = 0
        return
    }
}
major = targets[0]
minor = targets[1]
revision = targets[2]

OR

var targets:[UnsafeMutablePointer<Int>] = []
targets.append(&major)
targets.append(&minor)
targets.append(&revision)
for index in 0...2 {
    var scanner = NSScanner(string: components[index])
    if (!scanner.scanInteger(targets[index])) {
        major = 0
        minor = 0
        revision = 0
        return
    }
}

Upvotes: 0

Martin R
Martin R

Reputation: 540105

The problem is how to get a pointer to the variables at all. It is possible using withUnsafeMutablePointers():

init(string: String) {
    let components = string.componentsSeparatedByString(".")
    if 1...3 ~= components.count {
        withUnsafeMutablePointers(&major, &minor, &revision) {
            (p1, p2, p3) -> Void in
            let targets = [p1, p2, p3]
            for index in 0...2 {
                var scanner = NSScanner(string: components[index])
                if (!scanner.scanInteger(targets[index])) {
                    self.major = 0
                    self.minor = 0
                    self.revision = 0
                    break
                }
            }
        }
    }
}

but the code would probably better readable with three separate cases instead of a pointer array.

Upvotes: 3

Related Questions