SDK Setup Guides
...
Tutorials in Swift
Attachments: Chat App
this tutorial demonstrates how to work with an attachment in a chat app /#creating attachments /#replicating attachments syncing large documents can significantly impact network performance caution is advised when handling large binary data, such as a high resolution image or video exceeding 50 megapixels; a deeply embedded document; or a very large document instead of storing files exceeding 250kb directly within a document object, carefully consider using attachments for more information, see docid\ rb3wd2jhenojpw8xuirfy for the source code for the demo dittochat app for ios in the https //github com/getditto/demoapp chat/blob/main/ios/dittochat/data/dittoservice swift#l340 l350 github repository creating attachments the following snippet demonstrates how to create a new attachment in the demo chat app from the createimagemessage() function following the large image comment in the demo https //github com/getditto/demoapp chat/blob/main/ios/dittochat/data/dittoservice swift#l340 l350 app for ios code pass the user instance and the url path where the avatar image is stored create a new dittoattachment object by calling the newattachment() method since the demo dittochat app does not require end users to upload an avatar image, declare the new attachment as an optional object call the set() function and, using the dittomutabledocumentpath instance, pass the dittoattachment object the dittomutabledocumentpath instance links the user document object id to the attachment object and stores the attachment's data bytes and metadata properties to the given local ditto store (small peer) using the dittoattachmenttoken , initialize the attachment object later in the code, you'll invoke the dittoattachmenttoken to retrieve the attachment data from its current storage location, which could be either the ditto store or the peer to peer mesh network for more information, see docid\ yxemkh1com3csuumqcnlf , as follows func addavatar(to user user, imagepath string) { // optionally, add metadata as \[string string] let metadata = \[ "filename" "\\(userid) avatar png", "createdon" iso8601dateformatter() string(from date()) ] let attachment = collection newattachment( path imagepath, metadata metadata )! // add the attachment to the alice user document ditto store\["users"] findbyid(user id) update { mutabledoc in mutabledoc?\["avatartoken"] set(attachment) } } func addavatar(to user user, imagepath string) { // optionally, add metadata as \[string string] let metadata = \[ "filename" "\\(userid) avatar png", "createdon" iso8601dateformatter() string(from date()) ] let attachment = collection newattachment( path imagepath, metadata metadata )! // add the attachment to the alice user document ditto store\["users"] findbyid(user id) update { mutabledoc in mutabledoc?\["avatartoken"] set(attachment) } } note that on the user model, the avatartoken variable is of type dittoattachmenttoken, yet we call the set() function with a dittoattachment object this can be confusing the set() function, called with the attachment on a dittomutabledocumentpath instance, causes the data bytes of the attachment at the given file location to be stored in the ditto database, along with the metadata; the document property is initialized with a dittoattachmenttoken with which we will later fetch the attachment data asynchronously from the peer to peer mesh, or from local storage if it has already been fetched replicating attachments peers can now find the document, fetch the attachment, and use the attachment image if you want to update a progress view, use the progress event value in the following example, we've wrapped dittocollection fetchattachment(token\ deliveron\ onfetchevent ) in an imageattachmentfetcher struct for convenience struct imageattachmentfetcher { var fetcher dittoattachmentfetcher? init( ditto ditto, collection string, token dittoattachmenttoken, onprogress @escaping (double) > void, oncomplete @escaping (result\<uiimage, error>) > void ) { self fetcher = ditto store\[collection] fetchattachment(token token) { event in switch event { case progress(let downloadedbytes, let totalbytes) let percent = double(downloadedbytes) / double(totalbytes) onprogress(percent) case completed(let attachment) do { let data = try attachment getdata() if let uiimage = uiimage(data data) { oncomplete( success(uiimage)) } } catch { oncomplete( failure(error)) } default print("error event case \\(event) not handled") } } } } notice that we update a progress view by calling the imageattachmentfetcher struct with a progress handling closure and a completion handler for handling the fetched image since the attachment fetcher must remain a globally available instance for the entire duration of the asynchronous fetch operation, we maintain a strong reference to the attachment fetcher as indicated with a property if, at any time, the attachment fetcher goes out of scope, asynchronous fetch operations silently abort and the attachment api fails // properties var attachmentimage uiimage? var imagefetcher imageattachmentfetcher? let doc = collection findbyid(user id) exec()! let imagetoken = doc\["avatartoken"] attachmenttoken! imagefetcher = imageattachmentfetcher(ditto ditto, collection "users", token imagetoken, onprogress { percentcomplete in print("percent complete \\(percentcomplete)") }, oncomplete { result in switch result { case success(let uiimage) attachmentimage = uiimage case failure(let error) //handle error print(error localizeddescription) } } )