IOS swift how to know when activityViewController has been successfully used - ios

I have a tableView that utilizes the UIActivityViewController so users can share content on other 3rd party networks Facebook, twitter, text message etc. I have a function called IncreaseShareByOne() and it's purpose is to count the number of times that something has been shared . My problem is that right now that function fires of every time the UIActivityViewController is clicked . Is there someway that I can find out if a user really shared something so that I can use that function correctly ? becomes sometimes you open the UIActivityViewController and decide not to share anything so I want to catch and not use that function. I am new to swift and am using version 3 .
func sharedShareAction(controller: UIViewController, sender: UIButton) {
controller.present(activityViewController,animated: true,completion: nil)
IncreaseShareByOne()
}

You can add a completion handler to your UIActivityViewController. In the completion handler, check whether the user submitted using the completed value. You'll probably want to do something like this:
func sharedShareAction(controller: UIViewController, sender: UIButton) {
controller.present(activityViewController,animated: true, completion: nil)
activityViewController.completionWithItemsHandler = { activity, completed, items, error in
if !completed {
// handle task not completed
return
}
IncreaseShareByOne()
}
}
Check the API docs for more info.

Related

Facing issue in Siri Integration with custom intents

I’m trying to integrate Siri Shortcuts to my application. The concept which I’m trying is to get reward points of my card with secret pin confirmation. Please find what I have done for this below.
Enabled Siri in capabilities and added Siri Intent definition file.
Added new custom intent named say Rewards.
Defined the title. Subtitle and params(accType, pin) with confirmation enabled. Pin will be sent separately to user.
Then defined the intent response with param ‘rewardPoints’ and defined the response messages.
Added Siri intent extensions.
Added custom intent to info.plist files within project and intent extension.
Verified and added new handler for the custom intent and define the resolve, handle and confirm methods as below. For now, I’m returning random no for reward points.
//
// RewardsIntentHandler.swift
// SiriIntentExt
//
import UIKit
import Intents
class RewardsIntentHandler: NSObject, RewardsIntentHandling {
func resolveAccType(for intent:RewardsIntent, with completion: #escaping ([INStringResolutionResult]) -> Void) {
guard let accType = intent.accType else {
completion([INStringResolutionResult.needsValue()])
return
}
completion([INStringResolutionResult.success(with: accType)])
}
func resolvePin(for intent:RewardsIntent, with completion: #escaping ([INIntegerResolutionResult]) -> Void) {
guard let verifyPin = intent.pin else {
completion([INIntegerResolutionResult.needsValue()])
return
}
completion([INIntegerResolutionResult.confirmationRequired(with: verifyPin as? Int)])
}
func confirm(intent: RewardsIntent, completion: #escaping (RewardsIntentResponse) -> Void) {
completion(RewardsIntentResponse.init(code: RewardsIntentResponseCode.ready, userActivity: nil))
}
func handle(intent: RewardsIntent, completion: #escaping (RewardsIntentResponse) -> Void) {
guard intent.accType != nil else {
completion(RewardsIntentResponse.init(code: RewardsIntentResponseCode.continueInApp, userActivity: nil))
return
}
guard intent.pin != nil else {
completion(RewardsIntentResponse.init(code: RewardsIntentResponseCode.continueInApp, userActivity: nil))
return
}
let response = RewardsIntentResponse.success(rewardPoints: NSNumber(value: 3453))
completion(response)
}
}
Modified the IntentHandler to return rewards handler for rewards intent
//
// IntentHandler.swift
// SiriIntentExt
//
import Intents
class IntentHandler: INExtension {
override func handler(for intent: INIntent) -> Any {
if intent is RewardsIntent {
return RewardsIntentHandler()
}
return self
}
}
Donated the intent on view load as below.
//
// ViewController.swift
// Shortcuts
//
import UIKit
import Intents
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
siriAuthorisarion()
donateRewardIntent()
}
func siriAuthorisarion() {
INPreferences.requestSiriAuthorization { (status) in
print("Siri Authorization Status - ", status)
}
}
func donateRewardIntent() {
let rewardsIntent = RewardsIntent()
rewardsIntent.suggestedInvocationPhrase = "Reward Points"
rewardsIntent.accType = "test account"
let interaction = INInteraction(intent: rewardsIntent, response: nil)
interaction.donate { error in
if let error = error {
print("Donating intent failed with error \(error)")
}
DispatchQueue.main.async {
let alert = UIAlertController.init(title: ((error != nil) ? "Error" : "Success"), message: ((error != nil) ? "Oops!!! Error occured on donating intent." : "Intent donated succussfully!!!"), preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
}
I'm facing problem from the above code base. Siri is not requesting for pin and not able to get the exact reward points for the account.
Have following questions.
Can we add the intents programmatically to Siri instead adding from shortcuts app or settings. So that user can directly use the functionality once installing the application.
Once intent is added using Shortcuts app, I’m trying the ask Siri for reward points. Its immediately requesting for my app shortcuts defined. Once we say 'yes' to request, I need to be asked for pin. But Siri replies with some problem with my app. What to be done for asking for next param value.
In the handler file, I have added the resolve methods for each parameters. I feel, resolve methods are not getting called to validate the values. Do we need to handle anything to make resolve methods work?
How can I debug the handler implementation using breakpoint within resolve/handle/confirm methods.
Thanks in advance.
Find my analysis for the above questions.
Can we add the intents programmatically to Siri instead adding from shortcuts app or settings. So that user can directly use the functionality once installing the application.
By default, intents are provided for specific domains such as messaging, payments, photos, workout, etc. No need to explicitly add intents through shortcuts for theses specific domains. Apart from these domains if we are creating custom intent, we are in need to donate and add the intents to Siri using shortcut/settings application.
Once intent is added using Shortcuts app, I’m trying the ask Siri for reward points. Its immediately requesting for my app shortcuts defined. Once we say 'yes' to request, I need to be asked for pin. But Siri replies with some problem with my app. What to be done for asking for next param value.
From iOS13, Apple has added Siri parameters and Siri suggestion for custom intents to request the missing parameters. Till iOS12, we don't have parameters option for custom intents.
In the handler file, I have added the resolve methods for each parameters. I feel, resolve methods are not getting called to validate the values. Do we need to handle anything to make resolve methods work?
In iOS12, we cannot add resolve methods for parameters in custom intents. Resolve methods handled only for specific domains provided within Intents extensions as mentioned in question 1. From iOS13, we can have resolve methods for custom intents based on the parameters.
How can I debug the handler implementation using breakpoint within resolve/handle/confirm methods.
We can add breakpoints and debug intent handler methods.
Thanks.

How to know if user shared my app or not?

My app is all about getting points and winning money, and what I need to do is let the user share my app then give him some points.
The problem is that I don't know how to detect if the user truly shared the app or not
I'm using the following code:
func shareTapped(){
let text = "example"
let url = URL(string: "example.com")
let image = UIImage(named: "example_image")
let shareViewController = UIActivityViewController(activityItems: [text, image!, url!] ,applicationActivities: nil)
self.present(shareViewController, animated: true, completion: {() in
print("done")
})
}
The sharing method is working perfectly, but I was wondering if there is any delegate we can call in this situation.
Thanks.
So there is 2 scenarios where user can cancel share.
One is when UIActivityViewController present then there is a cancel button on UIActivityViewController from where user can cancel it and yes you can detect it with method
shareViewController.completionWithItemsHandler = { activity, completed, items, error in
}
In above method completed will be false if user canceled from UIActivityViewController cancel button. and it will return true if user share successfully but here comes second case with it.
So for second case suppose user want to share via watsapp and click on watsapp icon from UIActivityViewController and watsapp user list appear.
But there is a cancel button on that screen from where user can cancel sharing but still you will get completed flag true so there is no way you can detect if user click on cancel button from watsapp user list.

Calling screen dismiss on accept the twilio voice call even app is active in swift 4

I’m using Twilio’s Programmable Voice in one of the projects. My primary requirement is to place VoIP class between mobile devices. I am able to place calls from one device to another,but when i accept the call at that time calling screen is dismiss automatically and call continue in background. In this case user do not have an option for disconnect call or any other action related to call because screen is dismissed.
Here is the screen that i have created for call when app is in foreground.
Calling placed success fully but on receiver accept it will dismiss the custom screen.So that user do not have any option to disconnect call or any other action related to call.
If any issue in code or any thing related to call kit setting i need to configure or any other issue ? Please help.
As per my knowledge this is default behaviour of call kit framework. On accept button click it will dismiss the screen when app is in foreground. If you wants to achieve same like whats app then you need to create a custom screen for that.Below code I did to resolve this issue:
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction)
{
NSLog("provider:performAnswerCallAction:")
// TwilioVoice.configureAudioSession()
let vc = loadVC(strStoryboardId: SB_CHAT, strVCId: idVoiceCallVC) as! VoiceCallVC
vc.callername = name
vc.userPhoto = userphoto
APP_DELEGATE.appNavigation?.pushViewController(vc, animated: true)
assert(action.callUUID == self.callInvite?.uuid)
TwilioVoice.isAudioEnabled = false
self.performAnswerVoiceCall(uuid: action.callUUID)
{ (success) in
if (success)
{
action.fulfill()
}
else
{
action.fail()
}
}
action.fulfill()
}
You just need to add your custom screen display code in this delegate method of call kit framework.
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {}
Thanks.

How to close SFSafariViewController automatically when reaching a certain page

I want to close SFSafariViewController automatically upon reaching the "thank you" page of the Dropbox site after the user uploads something; it needs to automatically dismiss. How can I do that?
Here is what I have so far:
#IBAction func Singles5(_ sender: Any) {
let safariVC = SFSafariViewController(url: NSURL(string: "https://www.dropbox/Upload")! as URL)
self.present(safariVC, animated: true, completion: nil)
safariVC.delegate = self
}
One way I can think of is using the Custom URL scheme. You can specify your app's custom URL in the callback parameter of Dropbox (if Dropbox has callback). So when the user has finished uploading his/her file, dropbox executes the callback. In this case your app will receive the callback, with any parameters have you specified. This will call the function application(app, open, options)->Bool in your AppDelegate. Now, you can use a reference to the ViewController which presents the SFSafariViewController and call SafariViewController.dissmissViewController().

Social Framework doesn't work properly Swift

I want to have a share button in my app for sharing to Facebook.
I decided to do it with the social framework as i believed it was easier.
I was wrong...
Here is my code:
#IBAction func facebookButton(sender: AnyObject) {
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook) {
let fbSheet = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
fbSheet.setInitialText("Some text")
fbSheet.addImage(UIImage(named: "loading"))
fbSheet.addURL(NSURL(string: "http://www.something.com"))
presentViewController(fbSheet, animated: true, completion: nil)
} else {
self.showAlert("Facebook", msg: "Please login to your Facebook account in Settings")
}
}
This code is working, but it returns only the url and if I comment it; it returns only the image.
I have changed the order and I put image third but again it returns only the url.
It's like it has priorities and it returns only one of them.
Since last year Facebook doesn't allow to prefill the text if you want to share something. You can set only hashtags as setInitialText. something like this
fbSheet.setInitialText("#\(appname)")
https://developers.facebook.com/docs/apps/review/prefill

Resources