Help getting iOSKit’s MFMessageComposeViewController implemenation to accept attachments

I’ve run into a tough issue: I’m using iOSKit’s MFMessageComposeViewController to show the message composition view, but I need to add attachments. Some code was added to iOSKit, but it’s not used in the project’s test harness, so I can’t verify if it ever worked. It addAttachment method that’s crashing:

Public Function addAttachment(attachment as xojo.IO.FolderItem, MIMEType as text, fileName as Text) As Boolean
  Declare Function addAttachment_ Lib MessageUIKitLib Selector "addAttachmentData:mimeType:fileName:" _
  (obj_id As ptr, data As ptr, MIMEType As CFStringRef, fileName As CFStringRef) As Boolean
  
  Return addAttachment_(Self, NSDataFromFolderitem(attachment), MIMEType, fileName)
  
End Function

I’m familiar with this functionality in Objective-C, but I can’t pinpoint the cause of the crash in XOJO because it doesn’t drop in to the debugger, and the crash logs aren’t showing much:

Thread 0 name:   Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib        	       0x1ede51fbc __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x2107ef680 pthread_kill + 267
2   libsystem_c.dylib             	       0x1ae76ab90 abort + 179
3   libc++abi.dylib               	       0x210719ff8 abort_message + 131
4   libc++abi.dylib               	       0x210709f90 demangling_terminate_handler() + 347
5   libobjc.A.dylib               	       0x19ea1eda4 _objc_terminate() + 143
6   libc++abi.dylib               	       0x2107193bc std::__terminate(void (*)()) + 15
7   libc++abi.dylib               	       0x21071c758 __cxa_rethrow + 203
8   libobjc.A.dylib               	       0x19ea2ccbc objc_exception_rethrow + 43
9   CoreFoundation                	       0x1a66e54a8 CFRunLoopRunSpecific + 783
10  GraphicsServices              	       0x1e9c9b4f8 GSEventRunModal + 163
11  UIKitCore                     	       0x1a8b0b8a0 -[UIApplication _run] + 887
12  UIKitCore                     	       0x1a8b0aedc UIApplicationMain + 339
13  Test Attach.debug             	       0x100373228 runIOSMainLoop() + 124
14  Test Attach.debug             	       0x1000fc120 Xojo._RuntimeRun + 36
15  Test Attach.debug             	       0x100239760 _Main + 676
16  Test Attach.debug             	       0x100238a60 main + 36
17  dyld                          	       0x1c944edcc start + 2239

I’ve stripped most of the unnecessary stuff out of iOSKit framework and put together a simple project; it’s required to run on a realdevice because of messaging capabilities.

The sample project has a button to open the message composer, with or without an attachment (a JPEG file that’s copied into the app Resource folder at build time.)

The test code is simple but requires converting to the legacy datatypes, and f.Exists = true at runtime.

Self.MessageComposeView = New Extensions.MFMessageComposeViewController

If Switch_MessageAttachment.Value Then
  Dim file As FolderItem = SpecialFolder.Resource("image.jpeg")
  Dim type As Text = "image/jpeg"
  
  Dim f As New Xojo.io.FolderItem(file.NativePath.ToText)
  
  // Add our attachment
  Dim didAddImage As Boolean = Self.MessageComposeView.addAttachment(f, type, "image.jpeg")
  
  If Not didAddImage Then
    MessageBox("Couldn't attach the image.")
  End
End

If Extensions.MFMessageComposeViewController.canSendText Then
  Self.MessageComposeView.PresentInView(MobileScreen(App.CurrentLayout.Content))
Else
  MessageBox("This project needs to run on a real device")
End

The MIME type is JPEG; it’s definitely image/jpeg and it’s on the Apple documentation for the function:

Self.MessageComposeView.addAttachment is the entrypoint into the IOSKit functions.

I’ve also tried a version where instead of creating the NSData object from a file, I create it from a memoryblock, but it still crashes. I can’t imagine what it is with the two other parameters, which are Text objects.

Public Function addAttachment(attachment as xojo.IO.FolderItem, MIMEType as text, fileName as Text) As Boolean
  Declare Function addAttachment_ Lib MessageUIKitLib Selector "addAttachmentData:mimeType:fileName:" _
  (obj_id As ptr, data As ptr, MIMEType As CFStringRef, fileName As CFStringRef) As Boolean
  
  'Return addAttachment_(Self, NSDataFromFolderitem(attachment), MIMEType, fileName)
  
  // Try passing our own memory block (and keeping a reference to it
  Dim mb As XOJO.core.MemoryBlock = New XOJO.core.MemoryBlock(300)
  Self.retainedMB = mb
  Dim x As NSData = NSData.DataWithBytesLength(mb, 300)
  
  Return addAttachment_(Self, x, MIMEType, fileName)
  
End Function

Any assistance helping to track this problem down would be greatly appreciated. I know I’ll be crossing this bridge later with attachments MFMailComposeViewController. I’d really prefer the iOS message and mail composers for my application, rather than the generic share sheet:

John

Found the issue: the method signature used by the iOSkit declare was incorrect; it should be:

addAttachmentData:typeIdentifier:filename:

instead of

addAttachmentData:MIMEtype:filename:

:+1:

Glad you found the solution.

This might be my fault, IIRC, I wrote MFMessageComposeViewController, copying it from MFMailComposeViewController which has
addAttachmentData:MIMEtype:filename:

1 Like

No problem! PR submitted.

CC @Jason_King

1 Like

Thanks for submitting the fix! Looks like Jeremie already merged it :slight_smile:

1 Like