[arrays] 어레이의 정확한 복제본을 만들려면 어떻게합니까?

배열을 정확히 복제하려면 어떻게해야합니까?

Swift에서 배열 복제에 대한 정보를 찾는 데 어려움을 겪고 있습니다.

나는 사용해 보았다 .copy()

var originalArray = [1, 2, 3, 4]
var duplicateArray = originalArray.copy()



답변

배열은 Swift에서 전체 값 의미 체계를 갖기 때문에 멋진 것이 필요하지 않습니다.

var duplicateArray = originalArray 당신이 필요한 전부입니다.


배열의 내용이 참조 유형이면 예, 객체에 대한 포인터 만 복사합니다. 내용의 전체 복사를 수행하려면 대신 map각 인스턴스의 복사를 사용 하고 수행합니다. NSCopying프로토콜 을 준수하는 Foundation 클래스의 경우 다음 copy()메서드를 사용할 수 있습니다 .

let x = [NSMutableArray(), NSMutableArray(), NSMutableArray()]
let y = x
let z = x.map { $0.copy() }

x[0] === y[0]   // true
x[0] === z[0]   // false

여기에는 Swift의 값 의미 체계가 사용자를 보호하기 위해 작동하는 함정이 있습니다. 예를 들어, NSArray변경 불가능한 배열을 나타 내기 때문에 해당 copy메서드는 자신에 대한 참조를 반환하므로 위의 테스트는 예상치 못한 결과를 생성합니다.


답변

Nate가 맞습니다. 기본 배열로 작업하는 경우에는 duplicateArray를 originalArray에 할당하기 만하면됩니다.

완전성을 위해 NSArray 객체를 작업하는 경우 다음을 수행하여 NSArray의 전체 복사본을 수행합니다.

var originalArray = [1, 2, 3, 4] as NSArray

var duplicateArray = NSArray(array:originalArray, copyItems: true)


답변

Nate의 대답에 대한 세 번째 옵션이 있습니다.

let z = x.map { $0 }  // different array with same objects

* 편집 됨 * 여기서 편집 시작

위는 본질적으로 아래와 동일하며 실제로 아래의 같음 연산자를 사용하면 배열이 변경되지 않는 한 복사되지 않기 때문에 성능이 더 좋습니다 (설계에 의한 것임).

let z = x

자세한 내용은 https://developer.apple.com/swift/blog/?id=10을 참조하십시오.

* 편집 됨 * 편집은 여기서 끝납니다.

이 배열에 추가하거나 제거해도 원래 배열에는 영향을주지 않습니다. 그러나 배열이 보유하고있는 객체의 속성을 변경하면 원래 배열에서 볼 수 있습니다. 배열의 객체는 복사본이 아니기 때문입니다 (배열이 원시 숫자가 아니라 객체를 보유한다고 가정).


답변

일반 객체의 경우 복사를 지원하는 프로토콜을 구현하고 객체 클래스가 다음과 같이이 프로토콜을 구현하도록하는 것이 가능합니다.

protocol Copying {
    init(original: Self)
}

extension Copying {
    func copy() -> Self {
        return Self.init(original: self)
    }
}

그리고 복제를위한 어레이 확장 :

extension Array where Element: Copying {
    func clone() -> Array {
        var copiedArray = Array<Element>()
        for element in self {
            copiedArray.append(element.copy())
        }
        return copiedArray
    }
}

그것은보기 코드를 꽤 많이하고 샘플이 확인 요점을


답변

일부 클래스 객체의 배열 항목을 복사하려는 경우. 그런 다음 NSCopying 프로토콜을 사용하지 않고 아래 코드를 따를 수 있지만 개체에 필요한 모든 매개 변수를 가져와야하는 init 메서드가 있어야합니다. 다음은 놀이터에서 테스트 할 예제 코드입니다.

class ABC {

    var a = 0
    func myCopy() -> ABC {

        return ABC(value: self.a)
    }

    init(value: Int) {

        self.a = value
    }
}

var arrayA: [ABC] = [ABC(value: 1)]
var arrayB: [ABC] = arrayA.map { $0.myCopy() }

arrayB.first?.a = 2
print(arrayA.first?.a)//Prints 1
print(arrayB.first?.a)//Prints 2


답변