<!--
{
  "availability" : [
    "iOS: 17.0.0 -",
    "iPadOS: 17.0.0 -",
    "macCatalyst: 17.0.0 -",
    "visionOS: 1.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "MessageUI",
  "identifier" : "/documentation/MessageUI/MFMessageComposeViewController/setUPIVerificationCodeSendCompletion(_:)",
  "metadataVersion" : "0.1.0",
  "role" : "Instance Method",
  "symbol" : {
    "kind" : "Instance Method",
    "modules" : [
      "Message UI",
      "MessageUI"
    ],
    "preciseIdentifier" : "c:objc(cs)MFMessageComposeViewController(im)setUPIVerificationCodeSendCompletion:"
  },
  "title" : "setUPIVerificationCodeSendCompletion(_:)"
}
-->

# setUPIVerificationCodeSendCompletion(_:)

Configures the instance of a view for Unified Payments Interface (UPI) device validation.

```
func setUPIVerificationCodeSendCompletion(_ completion: @escaping (Bool) -> Void)
```

## Parameters

`completion`

A block that’s invoked with a `BOOL` to determine whether the message was sent. The send completion handler is invoked with `YES` after the SMS successfully transmitted to the sender’s cellular carrier. If the SMS failed to send, the completion handler invoked with `NO`.

## Discussion

If you use the <doc://com.apple.documentation/documentation/BundleResources/Entitlements/com.apple.developer.upi-device-validation> managed entitlement, [`setUPIVerificationCodeSendCompletion(_:)`](/documentation/MessageUI/MFMessageComposeViewController/setUPIVerificationCodeSendCompletion(_:)) configures the instance of [`MFMessageComposeViewController`](/documentation/MessageUI/MFMessageComposeViewController) with non-editable recipients and body fields.

> Note:
> The ``doc://com.apple.messageui/documentation/MessageUI/MFMessageComposeViewController/setUPIVerificationCodeSendCompletion(_:)`` method is only functional on devices with SMS capability and is only compatible with recipients that don’t use iMessage.

The system invokes the completion handler on the main thread. It only invokes the completion handler after the [`MFMessageComposeViewController`](/documentation/MessageUI/MFMessageComposeViewController) delegate’s [`messageComposeViewController(_:didFinishWith:)`](/documentation/MessageUI/MFMessageComposeViewControllerDelegate/messageComposeViewController(_:didFinishWith:)) method gets called if a person sends the transaction.

The system calls the send completion handler with the transmission result of the message. The system won’t call the completion handler if:

- The device doesn’t have SMS capability.
- Your app doesn’t have the <doc://com.apple.documentation/documentation/BundleResources/Entitlements/com.apple.developer.upi-device-validation> entitlement.
- The recipient can use iMessage or the person cancels the transaction.

The following code snippet is an example of how you can create an instance of [`MFMessageComposeViewController`](/documentation/MessageUI/MFMessageComposeViewController), configure it with a UPI verification phone number and generated token, and set a completion block indicating the use of the controller for UPI device enrollment:

```swift
import MessageUI.UPI

extension ViewController {
    func presentMessageComposer() {
        let composeController = MFMessageComposeViewController()
        composeController.messageComposeDelegate = self
        composeController.recipients = ["+14081234567"]
        composeController.body = "SomeDeviceVerificationCode123"
        composeController.setUPIVerificationCodeSendCompletion { result in
            NSLog("UPI send callback - message sent: \(result)")
        }
        
        present(composeController, animated: true)
    }
}
```

The following code snippet is the same as the one above, but in Objective-C:

```objc
@import MessageUI.UPI;

@implementation ViewController (MessageComposer)

- (void)presentMessageComposer {
    MFMessageComposeViewController *composeController = [[MFMessageComposeViewController alloc] init];
    composeController.messageComposeDelegate = self;
    composeController.recipients = @[@"+14081234567"];
    composeController.body = @"SomeDeviceVerificationCode123";
    [composeController setUPIVerificationCodeSendCompletion:^(BOOL result) {
        NSLog(@"UPI send callback - message sent: %@", result ? @"YES" : @"NO");
    }];
    
    [self presentViewController:composeController animated:YES completion:nil];
}

@end
```

In addition, you need to use the existing [`messageComposeViewController(_:didFinishWith:)`](/documentation/MessageUI/MFMessageComposeViewControllerDelegate/messageComposeViewController(_:didFinishWith:)) delegate method to dismiss the [`MFMessageComposeViewController`](/documentation/MessageUI/MFMessageComposeViewController) instance because sending may take several seconds to complete. You can choose to allow people to continue interacting with your app or display a waiting UI. The following code snippet is an example of using [`messageComposeViewController(_:didFinishWith:)`](/documentation/MessageUI/MFMessageComposeViewControllerDelegate/messageComposeViewController(_:didFinishWith:))

```swift
import MessageUI.UPI

extension ViewController: MFMessageComposeViewControllerDelegate {
    func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
        NSLog("messageComposeViewController didFinishWithResult \(result)")
        controller.dismiss(animated: true)
    }
}
```

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)