i'm trying to implement simple didReceiveTrust in XMPPStreamDelegate, but Xcode shows warning on method definition:
func xmppStream(_ sender: XMPPStream!, didReceiveTrust trust: SecTrust, completionHandler: XMPPStreamCompletionHandler) {
completionHandler(true)
}
warning is following:
Instance method
'xmppStream(sender:didReceiveTrust:completionHandler:)' nearly matches
optional requirement 'xmppStream(_:didReceive:completionHandler:)' of
protocol 'XMPPStreamDelegate'
when testing app i'm getting following in output:
2018-06-12 23:10:11:239 MyMessages[55145:3561831] XMPPStream: Stream
secured with (GCDAsyncSocketManuallyEvaluateTrust == YES), but there
are no delegates that implement
xmppStream:didReceiveTrust:completionHandler:. This is likely a
mistake.
please help
following function definition works as expected:
func xmppStream(_ sender: XMPPStream?, didReceive trust: SecTrust?, completionHandler: #escaping (_ shouldTrustPeer: Bool) -> Void) {
completionHandler(true)
}
Related
I wrote a simple Network Extension for iOS:
class CFilterDataProvider: NEFilterDataProvider {
override func startFilter(completionHandler: #escaping (Error?) -> Void) {
NSLog("startFilter...")
// Add code to initialize the filter.
completionHandler(nil)
}
override func stopFilter(with reason: NEProviderStopReason, completionHandler: #escaping () -> Void) {
// Add code to clean up filter resources.
NSLog("stopFilter")
completionHandler()
}
override func handleNewFlow(_ flow: NEFilterFlow) -> NEFilterNewFlowVerdict {
// Add code to determine if the flow should be dropped or not, downloading new rules if required.
return .drop()
}
}
After attaching to a process with Xcode, startFilter does not called in any situation.
My logs also indicate that function called successfuly but no action after attaching.
What's the reason for that?
I am currently working on implementing In App Purchases in my app and after restoring purchases i would like to call a completion to perform an action of displaying an alert to the user. I was doing it this way and found a post that says it might not even be executed. How can I properly structure this.
func restoreIAPPurchases(completion: (() -> Void)) {
if !self.canMakePayments {
return
}
self.paymentQueue.restoreCompletedTransactions()
completion()
}
let alertController = UIAlertController.vy_alertControllerWithTitle(nil, message: "Restore will reprocess your existing subscription. You will not be charged", actionSheet: false)
alertController.addAction("Ok")
alertController.addActionWithTitle("Restore", style: .default) {
IAPService.shared.restoreIAPPurchases {
UIAlertController.vy_showAlertFrom(self, title: "Restore complete", message: "Successfully restored purchase")
}
}
alertController.presentFrom(self)
"I was doing it this way and found a post that says it might not even be executed"
It might not be executed because you don't call the completion handler on all paths.
As Sh_Khan mentioned in his answer, you don't really need a completion handler here, you need to use the delegate methods to be informed when it completes and whether it was successful or not. But your particular issue with your specific code is that you are not calling completion in the if statement.
if !self.canMakePayments {
return
}
Should probably be
guard canMakePayments else {
completion()
return
}
In the code you had, if canMakePayments is false then your completion code will not execute.
The result is asynchonous here
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue)
or
func paymentQueue(_ queue: SKPaymentQueue,
restoreCompletedTransactionsFailedWithError error: Error)
Suppose I'm writing code for login and need Completion Hander for wait/call back after request completed.
//MARK:- #Properties
var signInCompletionHandler : ((_ result : AnyObject?, _ error : NSError?) -> Void)?
var viewController : UIViewController?
//MARK:- call login method with completion handler.
func login(withViewControler viewController : UIViewController, completionHandler : #escaping (_ result : AnyObject?, _ error : NSError?) -> Void) {
// Write your logic here.
}
I can't get the Apple Watch Complication to update/refresh in WatchOS 3. I I'm using the following code in my ComplicationController.swift file.
func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: #escaping (CLKComplicationTimeTravelDirections) -> Void) {
handler([.forward])
}
func getTimelineStartDate(for complication: CLKComplication, withHandler handler: #escaping (Date?) -> Void) {
handler(Date())
}
func getTimelineEndDate(for complication: CLKComplication, withHandler handler: #escaping (Date?) -> Void) {
handler(Date(timeIntervalSinceNow: 60 * 30))
}
I have also tried to schedule an update from the handle background task method in the ExtensionDelegate.swift but it dosen't seem to work either.
func scheduleNextRefresh() {
let fireDate = Date(timeIntervalSinceNow: 30 * 60)
let userInfo = ["lastActiveDate" : Date(),
"reason" : "updateWeekNumber"] as Dictionary
WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: fireDate, userInfo: userInfo as NSSecureCoding) { (error) in
if error == nil {
print("Succesfully updated week number")
}
}
}
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
for task: WKRefreshBackgroundTask in backgroundTasks {
if WKExtension.shared().applicationState == .background {
if task is WKApplicationRefreshBackgroundTask {
print("Task received")
scheduleNextRefresh()
}
}
task.setTaskCompleted()
}
}
WKRefreshBackgroundTask do not update anything itself, it just allows your app to go to active state and run code (placed somewhere around print("Task received") line) that will update your complication. Remember that number of WKRefreshBackgroundTasks is limited.
Complication can be updated such way:
let server = CLKComplicationServer.sharedInstance()
// if you want to add new entries to the end of timeline
server.activeComplications?.forEach(server.extendTimeline)
// if you want to reload all the timeline, which according to snippets looks like your case
server.activeComplications?.forEach(server.reloadTimeline)
This will cause system to call getCurrentTimelineEntry(for:withHandler:) methods of your CLKComplicationDataSource, where you can prepare and return updated entries.
More about complications update in documentation. More about background tasks in WWDC16 session.
I’m using INStartAudioCallIntentHandling in swift 2.3 and I’m getting this error :
Type ‘IntentHandler’ does not conform to protocol ‘INStartAudioCallIntentHandling’
I’m using Xcode 8.2.1. I put the func handle(startAudioCall intent: INStartAudioCallIntent, completion: (INStartAudioCallIntentResponse) -> Void) method into the class.Why i'm getting this error. Please help me.
you should probably also add
func confirm(startAudioCall: INStartAudioCallIntent, completion: (INStartAudioCallIntentResponse) -> Void)
and
func resolveContacts(forStartAudioCall: INStartAudioCallIntent, with: ([INPersonResolutionResult]) -> Void)
Use the methods of the INStartAudioCallIntentHandling protocol to
resolve, confirm, and handle requests to start an audio-only call with
the designated users. Adopt this protocol in an object of your Intents
extension that is capable of validating the call information.
source
Swift 3.1 solution.
We're passing in that user activity with Info that comes from the contacts display name. I'm going to need to say who I'm going to call.
I have this simple array that is a representation of a mock database. Maybe in your application have some kind of list of users that has all their contact information and you can check those contacts against the information that was passed into resolveContacts. The user says they want to call Dave, I make sure that that's in the database and if it is, then I call Dave. And in order to make the call, you need an INPerson, which requires a personHandle, which is basically a unique identifier for a human being.
You can either use an email or a phone number. I've chosen to go with a phone number right here. If it has the appropriate name, it creates this INPersonHandle, passes it in as a person with this phone number and whatever name, if it matches my existing contacts and then I say that the completion is successful with that person. If there is no matching contact, then we refer back to the user saying that we need a value.
import Intents
class IntentHandler: INExtension,INStartAudioCallIntentHandling {
override func handler(for intent: INIntent) -> Any? {
return self
}
func handle(startAudioCall intent: INStartAudioCallIntent, completion: #escaping (INStartAudioCallIntentResponse) -> Void) {
print("handle")
let ua = NSUserActivity(activityType: "Call")
let person:String = intent.contacts![0].displayName
ua.userInfo = ["person":person]
completion(INStartAudioCallIntentResponse(code: .continueInApp, userActivity: ua))
}
func confirm(startAudioCall intent: INStartAudioCallIntent, completion: #escaping (INStartAudioCallIntentResponse) -> Void) {
completion(INStartAudioCallIntentResponse(code: .ready, userActivity: nil))
}
func resolveContacts(forStartAudioCall intent: INStartAudioCallIntent, with completion: #escaping ([INPersonResolutionResult]) -> Void) {
print("resolveContacts")
let contacts:[String] = ["Dave","James","Herman"]
for contact in contacts {
if intent.contacts?[0].spokenPhrase?.uppercased() == contact.uppercased() {
let personHandle:INPersonHandle = INPersonHandle(value: "1-555-555-5555", type: .phoneNumber)
let person:INPerson = INPerson(personHandle: personHandle, nameComponents: nil, displayName: contact, image: nil, contactIdentifier: nil, customIdentifier: nil)
completion([INPersonResolutionResult.success(with: person)])
return
}
}
completion([INPersonResolutionResult.needsValue()])
}
}
Say I have a function that has a completion handler, then calls another function, with a completion handler like this:
func register(withCompletion complete: #escaping (() -> Void)) {
self.sendRegisterRequest(withCompletion: { (error: Error?) -> () in
if error != nil {
self.performSegue(withIdentifier: "ErrorVCSegue", sender: nil)
}
else {
complete()
}
})
}
In the event of an error, it will segue away with calling complete().
Am I ok to segue away like this, without calling complete()? I do not need to return from this function as I'm now wanting to go to another View Controller.
Thanks.
This is a bad idea. A completion handler should be called no matter what. The caller is waiting for a response. It wants to know when it is done. That's the whole point of having a completion handler.
In your case (like many other cases), it would be much better if the completion handler accepted a boolean parameter (and/or an error parameter). This way the completion handler provides some basic information about the success or failure of the method.
Try like this
override func viewDidLoad() {
super.viewDidLoad()
register { (error) in
if error == nil {
// do what you want in success case
} else {
self.performSegue(withIdentifier: "ErrorVCSegue", sender: nil)
}
}
}
func register(withCompletion complete: #escaping ((_ error: Error?) -> Void)) {
self.sendRegisterRequest(withCompletion: { (error: Error?) -> () in
complete(Error)
})
}
Thanks:)