Swift에서 쓰기 함수를 사용하여 NSOutputStream에 NSData 바이트를 쓰는 중 오류("'()'는 'UInt8'"과 동일하지 않습니다)

StackOverflow https://stackoverflow.com//questions/25080661

  •  02-01-2020
  •  | 
  •  

문제

저는 Swift를 기반으로 비동기 파일 다운로드를 구축하려고 합니다. 에리카 사둔의 방법.하지만 더 큰 파일을 처리하려면 그것이 필요해서 찾았습니다. NSData 대신 NSOutputStream 사용에 대한 답변, 말이된다.

그러나 나는 그것을 작동시킬 수 없습니다.NSOutputStream 쓰기 함수에 NSData 바이트(NSURLConnection didReceiveData 함수에 있음)를 추가하려고 하면 이 오류가 발생합니다. '()' is not identical to 'UInt8' 이 행에서: bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite).

data.bytes 유형이다 ConstUnsafePointer<()> 그리고 .write() 함수는 유형이 다음과 같을 것으로 예상합니다. ConstUnsafePointer<UInt8>, 그런 의미에서 오류는 완벽하게 이해됩니다.하지만 저는 iOS와 Swift 프로그래밍을 처음 접했기 때문에 이 문제를 해결하는 방법을 이해할 수 없습니다.

그럼 어떻게 변환하나요? data.bytes: ConstUnsafePointer<()> 에게 ConstUnsafePointer<UInt8> 대체이 작업을 다른 방식으로 수행하시겠습니까?

나의 didReceiveData 기능:

func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {

    var bytesLeftToWrite: NSInteger = data.length
    var bytesWritten: NSInteger = 0

    while bytesLeftToWrite > 0 {

        bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite)

        if bytesWritten == -1 {

            break

        }

        bytesLeftToWrite -= bytesWritten

        let responseExpectedlenght: NSNumber = NSNumber(longLong: self.downloadResponse!.expectedContentLength)
        let dataLength: NSNumber = NSNumber(long: data.length)

        self.downloadProgressPercentage = ((dataLength / responseExpectedlenght) * 100)

        println("Downloaded: \(self.downloadProgressPercentage)%")

    }

}
도움이 되었습니까?

해결책

다음을 사용하여 포인터를 캐스팅할 수 있습니다. UnsafePointer():

bytesWritten = self.downloadStream.write(UnsafePointer(data.bytes), maxLength: bytesLeftToWrite)

쓰기 루프에도 문제가 있습니다. 왜냐하면 항상 다음을 작성하기 때문입니다.초기의 데이터 객체의 바이트를 출력 스트림으로 보냅니다.

아마도 다음과 유사할 것입니다(테스트되지 않음).

var bytes = UnsafePointer<UInt8>(data.bytes)
var bytesLeftToWrite: NSInteger = data.length

while bytesLeftToWrite > 0 {
    let bytesWritten = self.downloadStream.write(bytes, maxLength: bytesLeftToWrite)
    if bytesWritten == -1 {
        break // Some error occurred ...
    }

    bytesLeftToWrite -= bytesWritten
    bytes += bytesWritten // advance pointer

    // ...
}

다른 팁

나는 당신 자신을 활용하는 것이 좋습니다 enumerateByteRangesUsingBlock, 왜냐하면 NSData 더 이상 기본 데이터가 단일 연속 메모리 블록에 유지된다는 보장이 없습니다.예를 들어, 문서에 따르면 didReceiveData ~의 NSURLSessionDataDelegate 규약:

왜냐하면 NSData 객체는 종종 여러 다른 데이터 객체로부터 함께 결합됩니다. 가능할 때마다 다음을 사용하십시오. NSData'에스 enumerateByteRangesUsingBlock: 메서드를 사용하는 대신 데이터를 반복하는 방법 bytes 방법 (평평화 NSData 단일 메모리 블록에 개체를 넣습니다).

따라서 예를 들어 다음과 같은 확장을 수행할 수 있습니다. NSOutputStream 그 내용을 쓰는 것은 NSData:

extension NSOutputStream {

    /// Write contents of NSData to `NSOutputStream`
    ///
    /// - parameter data:   The `NSData` being written to the stream.
    ///
    /// - returns:          The number of bytes written. In case of error, returns -1.

    func writeData(data: NSData) -> Int {
        var totalBytesWritten = 0

        data.enumerateByteRangesUsingBlock() {
            buffer, range, stop in

            var bytes = UnsafePointer<UInt8>(buffer)
            var bytesWritten = 0
            var bytesLeftToWrite = range.length

            while bytesLeftToWrite > 0 {
                bytesWritten = self.write(bytes, maxLength: bytesLeftToWrite)
                if bytesWritten < 0 {
                    stop.initialize(true)
                    totalBytesWritten = -1
                    return
                }

                bytes += bytesWritten
                bytesLeftToWrite -= bytesWritten
                totalBytesWritten += bytesWritten
            }
        }

        return totalBytesWritten
    }

}

오류가 발생한 경우 열거를 중지하는 기술, 즉 stop.initialize(true), Xcode 6 베타 4 이상이 필요합니다.이전 버전의 Xcode(및 관련 컴파일러)는 열거를 중지하기 위해 부울 참조를 업데이트하는 데 더 어색한 구성을 사용했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top