Create an attachment (pdf data) in couchbase lite ios Swift 3

Hi, the developer docs suggest this code to create an attachment from Swift code in iOS:

// Add or update an image to a document as a JPEG attachment:
let doc = db.documentWithID("Robin")
let newRev = doc.currentRevision.createRevision()
let imageData = UIImageJPEGRepresentation(photo, 0.75)
newRev.setAttachmentNamed("photo.jpg", withContentType: "image/jpeg", content: imageData)
var error: NSError?
assert(newRev.save(&error) != nil)

This is not Swift 3, though.

let newRev = document?.currentRevision?.createRevision()
if let newRev = newRev {
	
	newRev.setAttachmentNamed(pdfName + ".pdf", withContentType: "application/pdf", content: pdfContentsData)
	do {
		
		try newRev.save()
		
	} catch let error as NSError {
	
		writeError = error
		resultFlag = false
	}
}

But the above code that is acceptable by the Swift 3 compiler fails:

2017-07-06 12:47:26.210306+0100 Xxxxx App[12401:718504] *** ASSERTION FAILED: !revID || [revID isKindOfClass: [CBL_RevID class]]
2017-07-06 12:47:26.210562+0100 Xxxxx App[12401:718504] *** Assertion failure in -CBL_Revision initWithDocID:revID:deleted:, /Users/jenkins/jenkins/workspace/couchbase-lite-ios-builds/couchbase-lite-ios-community/Source/CBL_Revision.m:45
2017-07-06 12:47:26.223465+0100 Xxxxx App[12401:718504] *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘!revID || [revID isKindOfClass: [CBL_RevID class]]’
*** First throw call stack:
(
0 CoreFoundation 0x000000010a8f079b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010da43121 objc_exception_throw + 48
2 CoreFoundation 0x000000010a8f5852 +[NSException raise:format:arguments:] + 98
3 Foundation 0x000000010d5281df -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 165
4 Xxxxx App 0x0000000108fbfaf5 _AssertFailed + 485
5 Xxxxx App 0x0000000108f501a1 -[CBL_Revision initWithDocID:revID:deleted:body:] + 0
6 Xxxxx App 0x0000000108fc9ddc -[CBLDatabase(Insertion) putDocID:properties:prevRevisionID:allowConflict:source:status:error:] + 676
7 Xxxxx App 0x0000000108f8bc1f -[CBLDocument putProperties:prevRevID:allowConflict:error:] + 197
8 Xxxxx App 0x0000000108f908fd -[CBLUnsavedRevision save:] + 113
9 Xxxxx App 0x0000000108c089db T09Forms_App0A16JSONStoreManagerC18writePDFBackgroundSb7success_So7NSErrorCSg5errorts10DictionaryVySSypGFyycfU + 4411
10 Xxxxx App 0x0000000108c08f81 _T09Forms_App0A16JSONStoreManagerC18writePDFBackgroundSb7success_So7NSErrorCSg5errorts10DictionaryVySSypGFyycfU_TA + 273
11 Xxxxx App 0x0000000108a38649 _T0Ix_IyB_TR + 41
12 libdispatch.dylib 0x000000011216bbb9 _dispatch_client_callout + 8
13 libdispatch.dylib 0x0000000112172500 _dispatch_queue_barrier_sync_invoke_and_complete + 92
14 Xxxxx App 0x0000000108c0771f _T09Forms_App0A16JSONStoreManagerC18writePDFBackgroundSb7success_So7NSErrorCSg5errorts10DictionaryVySSypGF + 1487
15 Xxxxx App 0x0000000108a5d183 _T09Forms_App0A18ProcessorCBServiceC17savePDFBackgroundy10Foundation4DataV03pdfH0_SS7forNameSS12withCategorySS7versionys9AnyObject_pSg_s5Error_pSgtc13andCompletiontF + 1923
16 Xxxxx AppTests 0x000000012d5edff9 T014Forms_AppTests0a19ProcessorCBService_C0C21testSavePDFBackgroundyyFy10Foundation4DataVSg_s5Error_pSgtcfU + 825
17 Xxxxx AppTests 0x000000012d5ee4a8 _T014Forms_AppTests0a19ProcessorCBService_C0C21testSavePDFBackgroundyyFy10Foundation4DataVSg_s5Error_pSgtcfU_TA + 232
18 FileProvider 0x000000010b9f8446 T012FileProvider05LocalaB0C8contentsAA15OperationHandle_pSgSS4path_y10Foundation4DataVSg_s5Error_pSgtc17completionHandlertFyAH3URLVcfU_yycfU + 102
19 FileProvider 0x000000010ba0279a _T012FileProvider05LocalaB0C8contentsAA15OperationHandle_pSgSS4path_y10Foundation4DataVSg_s5Error_pSgtc17completionHandlertFyAH3URLVcfU_yycfU_TA + 106
20 FileProvider 0x000000010b8e5e89 _T0Ix_IyB_TR + 41
21 libdispatch.dylib 0x000000011216abd1 _dispatch_call_block_and_release + 12
22 libdispatch.dylib 0x000000011216bbb9 _dispatch_client_callout + 8
23 libdispatch.dylib 0x0000000112171c98 _dispatch_continuation_pop + 492
24 libdispatch.dylib 0x0000000112170361 _dispatch_async_redirect_invoke + 796
25 libdispatch.dylib 0x00000001121767b8 _dispatch_root_queue_drain + 581
26 libdispatch.dylib 0x000000011217650c _dispatch_worker_thread4 + 47
27 libsystem_pthread.dylib 0x00000001125c85a2 _pthread_wqthread + 1299
28 libsystem_pthread.dylib 0x00000001125c807d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

What am I doing wrong?

All other db access code sections (those outside the specific attachment stuff) do work…

Thanks,
Aldo

This looks like a Couchbase Lite bug, not anything you’re doing wrong. Are you using the latest release, 1.4? If not, please upgrade and try again. If you’re on 1.4, please file an issue on Github including that backtrace. Thanks!

Jen,

thanks for your answer! That’s good to hear, as I was really running out of ideas.

FYI: it must be a very funny bug (if it really is one).

After posting I still had a problem to solve. So I did look around some more time; finally -to see other people’s code- I did download the Todo sample app from the docs site. Added the same CBL lib (the latest, 1.4) with CocoaPods and ran it. Attachments do work. I even extracted a somewhat more elegant way to do the attach to doc operation, breaking it then in two separate steps:
[
func writeEnvelope(_ pdfBGInfo: [String: Any]) -> (success: Bool, error: NSError?) {

    /* pdfBackground
     
     "ID": <String>,
     "name": <String>,
     "version": <String>
     "name": <String>,
     "category": <String>,
     "tags": [<String>],
     */
    
    var resultFlag: Bool = true
    var writeError: NSError? = nil
    var backgroundEnvelope: [String: Any] = pdfBGInfo
    
    var pdfID: String = ""
    let pdfName = backgroundEnvelope["name"] as? String
    
    self.couchbaseQueue?.sync {
        
        if let pdfName = pdfName {
            
            backgroundEnvelope[kDocumentType] = kFormPDFBackgroundDocument as AnyObject?
            
            let pdfIDStr = backgroundEnvelope[kIDKey] as? String
            if let pdfIDStr = pdfIDStr {
                
                pdfID = pdfIDStr
            }
            
            let document = self.database!.document(withID: pdfID)
            
            do {
                
                try document?.putProperties(backgroundEnvelope)
                
            } catch let error as NSError {
                
                writeError = error
                resultFlag = false
            }
        }
    }
    
    return (success: resultFlag, error: writeError)
}

] and [

func attachPDF(envelopeID: String, data: Data) -> (success: Bool, error: NSError?) {
    
    var resultFlag: Bool = true
    var attachError: NSError? = nil

// self.couchbaseQueue?.sync {

    let readDoc = self.database?.document(withID: envelopeID)
    
    if let readDoc = readDoc {
        
        do {
            try readDoc.update({ (newRev) -> Bool in

// let photo = UIImage(named: “Face - 6”)
// let otherData = UIImageJPEGRepresentation(photo!, 0.75)
newRev.setAttachmentNamed(“pdf”, withContentType: “application/pdf”, content: data)

                return true
            })
            
        } catch let error as NSError {
            
            attachError = error
            resultFlag = false
        }
    }
    
    //        }
    
    return (success: resultFlag, error: attachError)
}

]
Still, the problem is still there for me.

BTW: I am now working day-to-day on Xcode 9b2. Just for curiosity I made an attempt to see if the latest Xcode 8 would make any difference (even if CBL is Obj-C, so I would not expect to see any different result). It does not.

Still, it’s funny to note that the Todo app works nicely with attachments.

I will make a report!

Thanks,
Aldo

Sorry!

Early morning typo: still have to go to the coffee machine…

** Jens **

BTW: Would it make sense to test with CBL 1.5 and/or the 2.0 Dev build?

If it’s an option, I would recommend using CBL 2.0 /SG 1.5. There are lot of under-the-hood performance improvements to the platform and from the app developer’s perspective, you have a completely revamped API thats simpler and cleaner.
Of course, since its a Developer Build, there may be changes with subsequent releases which may need updates to your app. Attachment handling has also slightly changed in 2.0. We have a blob data type that you can use .

Thanks: I will give it a go once I have a stable codebase on my side…

Aldo

Great. We’d love to get your feedback on the new builds.