Represent NSData in String in compact way

Parse.com supports local database, use case is to save file locally first then later upload to server when internet is available.

Offline time maybe weeks.

Native solution as saving data as PFFile (s3) doesn’t work in this case.

Need to find a way to save NSData in String then save as a regular parse db column.

There is a size limit of 128kb for each column.

Good news is my files aren’t too large, one docx is only 86kb.

The problem is if I use NSData.hexstring representation, (same as data.description), the string representation size is quite big, up to 176kb, almost doubled from original 86kb.

Found 2 github lib, (https://github.com/1024jp/NSData-GZIP) and (https://github.com/leemorgan/NSData-Compression), compress ratio aren’t good enough.

original file size: 86069
original string representation size: 172152
size compressedDataLZ4: 163114
size compressedDataLZFSE: 163538
size compressedDataLZMA: 162296
size compressedDataZLIB: 161740

compress size using gzip: 161712

Must be a better way to represent nsdata in string.

For now, this works. At least the docx file can be open after conversion.


let str = NSString(data: self.docData!, encoding: NSWindowsCP1254StringEncoding)
print("original size: \((str as! String).characters.count)");

let data = str?.dataUsingEncoding(NSWindowsCP1254StringEncoding, allowLossyConversion:false )

let tmpPath = NSString(string:"~/tmp/")  .stringByExpandingTildeInPath

let result = data?.writeToFile(tmpPath+"/1.docx", atomically: true)

In fact the base64encoding for NSData is pretty small already. no need to waste time to compress by yourself.

Advertisements

Learning RxSwift – rewrite Variable

Code example of how to implement prepend and append newer/older items to an existing(already bounded) list.

import Foundation
import RxSwift

func fetchEarlierItemsThan(latestItem: Int?) -> Observable<[Int]> {
    if let latestItem = latestItem {
        return just([latestItem - 1])
    }
    return just([0])
}

func fetchLaterItemsThan(latestItem: Int?) -> Observable<[Int]> {
    if let latestItem = latestItem {
        return just([latestItem + 1])
    }
    return just([0])
}

let prependStream = PublishSubject<Void>()

let appendStream = PublishSubject<Void>()

let currentPostList = Variable([Int]())

let prependItems = prependStream
    .withLatestFrom(currentPostList.asObservable()) { _, prependItems -> Observable<[Int]> in
        return fetchEarlierItemsThan(prependItems.first)
            .map { newItemsToPrepend in newItemsToPrepend + prependItems }
    }
    .switchLatest()
    .subscribeNext {
        currentPostList.value = $0
    }

let appendItems = appendStream
    .withLatestFrom(currentPostList.asObservable()) { _, appendItems -> Observable<[Int]> in
        return fetchLaterItemsThan(appendItems.last)
            .map { newItemsToAppend in appendItems + newItemsToAppend }
    }
    .switchLatest()
    .subscribeNext {
        currentPostList.value = $0
}

currentPostList.subscribeNext {
    NSLog("\($0)")
}

appendStream.onNext(())
prependStream.onNext(())
appendStream.onNext(())
prependStream.onNext(())
prependStream.onNext(())
prependStream.onNext(())

playground output:
2016-01-08 11:46:23.031 Introduction[60454:5285520] []
2016-01-08 11:46:23.035 Introduction[60454:5285520] [0]
2016-01-08 11:46:23.039 Introduction[60454:5285520] [-1, 0]
2016-01-08 11:46:23.042 Introduction[60454:5285520] [-1, 0, 1]
2016-01-08 11:46:23.045 Introduction[60454:5285520] [-2, -1, 0, 1]
2016-01-08 11:46:23.049 Introduction[60454:5285520] [-3, -2, -1, 0, 1]
2016-01-08 11:46:23.052 Introduction[60454:5285520] [-4, -3, -2, -1, 0, 1]