خطأ ("'() 'ليست متطابقة إلى 'وينت 8'") كتابة بايت نسداتا إلى نسوتبوستريم باستخدام وظيفة الكتابة في سويفت
سؤال
أحاول إنشاء تنزيل ملف غير متزامن في سويفت بناء على طريقة إيريكا سادون.ولكن أنا في حاجة إليها للتعامل مع ملفات أكبر ، لذلك وجدت هذه الإجابة حول استخدام نسوتبوتستريم بدلا من نسداتا, ، من المنطقي.
ومع ذلك ، لا أستطيع الحصول عليه للعمل.أحصل على هذا الخطأ عندما أحاول إضافة بايت نسداتا (في بلدي نسورلكونكتيون ديدريسيفيداتا وظيفة) إلى وظيفة الكتابة نسوتبوتستريم: '()' is not identical to 'UInt8'
في هذا الصف: bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite)
.
data.bytes
هو من النوع ConstUnsafePointer<()>
و ال .write()
تتوقع الوظيفة أن يكون النوع ConstUnsafePointer<UInt8>
, ، لذلك بهذا المعنى ، فإن الخطأ منطقي تماما.ولكن بما أنني جديد على دائرة الرقابة الداخلية وبالطبع البرمجة السريعة ، لا أستطيع الحصول على رأسي حول كيفية إصلاح هذا.
لذلك ، كيف يمكنني تحويل 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)
, ، يتطلب كسكودي 6 بيتا 4 أو في وقت لاحق.الإصدارات السابقة من كسكودي (والمترجم المرتبطة بها) تستخدم بناء أكثر حرج لتحديث إشارة منطقية لوقف التعداد.