I'm trying to initiate a call which also contains DTMF Numbers
ex:- 012345678,1*0001*000*1*1#
and i'm using the following code to initiate the call
guard let number = URL(string: "tel://" + number) else { return }
UIApplication.shared.open(number)
and then the systems shows popup to the user to make the call with the Full number also including the DTMF.
so i was wondering if it is possible that we can hide the DTMF part from that Popup ?
so the user only sees "012345678" instead of "012345678,1*0001*000*1*1#" as this DTMF numbers are secure data that he shouldn't see it.
Thanks
That's not possible, as far as I know. That popup is created by iOS itself and you have no control over it.
Related
I have a WebView that loads an URL (say login.salesforce.com) & asks the user to login to his instance.
Now, I want to get rid of the default login screen that it shows up & want to play around with the color of the login button.
Is it possible to change the color of a button inside a website that loads in UIWebView or WKWebView?
Absolutely Yes. For this you need to have little bit knowledge of html,css and java script.
Step 1. Prepare a java script as a string like below:
let changeHtmlbuttonScript = """
var property = document.getElementById(btn);
if (count == 0) {
property.style.backgroundColor = "#FFFFFF"
count = 1;
} else {
property.style.backgroundColor = "#7FFF00"
count = 0;
}
"""
Step 2: Evaluate java script on your current webview
self.webView.evaluateJavaScript(self.changeHtmlbuttonScript)
You can do it with UIWebView if you override the resource loading with a custom NSURLProtocol, and load your own CSS instead of theirs. "evaluateJavaScript" might work as well if you wait until the page is loaded somehow (see other reply).
Most likely what you ask violates the Salesforce's terms of service, so I wouldn't do it.
If they have a REST API for something that you try to achieve, then you can provide your own UI.
I am developing a multi player game. I want to use "standard" GKMatchmakerViewController for finding players like this:
let matchrequest = GKMatchRequest()
matchrequest.minPlayers = 2
matchrequest.maxPlayers = 2
matchrequest.defaultNumberOfPlayers = 2
matchrequest.inviteMessage = "Hello, do you want to play with me ?"
let mmVC = GKMatchmakerViewController(matchRequest: matchrequest)
mmVC?.matchmakerDelegate = self
self.present(mmVC!, animated: true)
If I invoke the GKMatchmakerViewController on both devices and press "Play now" they find each other and everything ist fine.
However when I press "Invite Friends", press the "+" on the right to add a recipient and go then to the tab "Nearby" NO players show up.
Q1: Why don't I see the player in "Nearby" but can connect to it by pressing "Play now"
Q2: If I send an invitation to my other player via iMessage the message is received on the other device and when I click it the app gets launched. But it remains at its Main Screen and doesn't take any action to respond to the invitation. What Protocol or Callback needs to be implemented in order to react to app launches caused by "game invitations" ?
Please refer to the latest API. The GC APIs have changed dramatically and most SO answers refer to the deprecated API.
Thanks
Chris
For Q2. you need to implement GKLocalPlayerListener to answer calls.
How were you able to send invites? I'm trying to figure out how to get a GKPlayer from a string. Like If I want to send an invite to my friend "Blazing420" how do I know his GKPlayer ID or how do I find him, since GKMatchRequest.recipients only takes GKPlayers as arguments.
I create numbers array from CNContact in singleton. But when I reload my CallKit extensions CallKit doesn't block number that I blocked before. Number length is 11 characters. Array isn't null. After reload CallKit Extension there is no error.
static let shared = BlockNumbersManager()
private init() { }
open var blockNumbers: [CXCallDirectoryPhoneNumber] = []
open func getIntegerBlockNumbers() -> [CXCallDirectoryPhoneNumber] {
return blockNumbers
}
private func addBlockingPhoneNumbers(to context: CXCallDirectoryExtensionContext) throws {
let phoneNumbers: [CXCallDirectoryPhoneNumber] = BlockNumbersManager.shared.getIntegerBlockNumbers() // TODO: add numbers for block dynamically.
for phoneNumber in phoneNumbers {
context.addBlockingEntry(withNextSequentialPhoneNumber: phoneNumber)
}
}
What have I missed?
While #Stuart 's answer makes quite good points, I'd like to add some tips from my side, after I spent over 1 hour to figure out why my Call Directory extension did not work...
The phone number format: check if you've added the country code. In my case I tested with Australian mobile number like 0412345678, so it should be either 61412345678, or +61412345678. Yes both worked for me.
Mind the iOS cache! What you've written in your Call Directory extension does not get executed/called each time you restart or run your app. i.e. You think you've appended some new phone numbers in the blocking array but iOS actually may not load it as you expected. The trick is to toggle your app's option in Settings -> Phone -> Call Blocking & Identification.
You may want to call CXCallDirectoryManager.reloadExtension in your main app when a reload is needed to invalidate the iOS cache.
Currently in iOS 10.x, every time your Call Directory extension runs it must provide a complete set of phone numbers to either block or identify with a label. In other words, if it runs once and adds blocked phone numbers [A, B, C], and you wish to also block phone number D, then the next time the extension is run it must provide the complete list [A, B, C, D].
In iOS 11, some new APIs have been added which allow the extension to provide data incrementally whenever possible. For instance, if the extension has already run once and added blocked phone numbers [A, B, C], and you wish to also block phone number D, then the next time the extension is run it may first check if the system allows incremental loading, and if it does then it may add blocked numbers [D] and the full list of blocked numbers will become [A, B, C, D].
Note that when using the new iOS 11 incremental loading APIs, your extension must always check whether incremental loading is currently allowed. The system may occasionally need to reload the complete list of phone numbers and your extension must remain able to provide the complete list.
See the documentation for these new APIs at https://developer.apple.com/documentation/callkit/cxcalldirectoryextensioncontext
In addition, you may view the 'Call Directory Extension' iOS extension template in Xcode 9 which has been updated to demonstrate the new incremental loading APIs:
Check each phone number in your contact list, if any number without country code are listed then it will not added to blocking list, you must have to provide Country code + Number
1. Clicking the link causes a database update.
There is a certain link I have access to (let's pretend it's www.google.com), such that when I open it up in my browser, it updates a certain section of the JSON code in my database. Based on the numbers that make up a portion of the link, it adjusts a certain value in the data.
2. How do I run this link in the background of my iOS app?
I need to be able to "open" this link within the app, without actually opening up a UIWebview and visually visiting the site. I just need this JSON data inside the database to update on its own (with the user unaware that it even happened).
The problem I'm having here is that I simply don't know how this is done. How do I cause this link to be visited without opening up a Safari browser?
The best approach I've found for such functions is to treat them as if they were "AJAX" (or "REST", "API", etc.) - while these terms are often used (and for more seasoned programmers instantly give a certain thought), the end result is that they take information from your 'originator' and send to the 'server' for processing, which then replies with a 'response'. Once you get that concept in your head, this becomes a fairly simple activity.
(for our example, I will call this "API", as that does really suit {as #Mortiz suggested} this question best)
For Swift 3, there are several ways to do this, I'll show you two I've found and use for various functions:
DispatchQueue
For a 'one-time shot to a url that I know exists and will connect reliability', this is a good one to use (think of it as a 'quick-n-dirty' if you like....!)
DispatchQueue.global().async {
let data = try? Data(contentsOf: theURL!) //make sure your url does exist, otherwise unwrap in a if let check / try-catch
DispatchQueue.main.async {
// do stuff here with the data if you need
// you can get the response from the server and parse it out, set buttons in the app, etc.
}
}
Alamofire
For Swift 3, Alamofire is extremely popular and does a lot of great stuff. Check it out if you haven't already!
Alamofire.request("\(theURL!)").responseJSON { response in
print("result is ", response.result)
switch response.result {
case .success(let value):
// do stuff with the returned data
// like updating your internal database, etc.
print(value)
case .failure(let error):
print("There was an error")
// you can see the error response in various ways....
print(requested)
print(error)
print(response)
print(response.result)
}
}
Once you have your buttons in place (from your description it sounds like that is what your #1 is about), then in the function you call when it is clicked, drop in the code from above and 'do stuff' as you need.
This will make the update to the server automatically in the background (answering your #2) - the user won't notice anything unless there are connection issues to the internet, etc. (much too complex to get into here, though if you expect to have much of it, Alamofire is a great choice as it automatically retries, etc. (part of the great features you should check out)
A key piece of this is that you can take the response from the URL (send various bits of JSON data back from the server, then break it back down in the phone) and do 'whatever' with it.
Some things you can do (to hopefully give you more ideas - which is just about anything.....):
update data in the app (local storage, local variables, etc.)
update text (color, background) inside Buttons or Labels
process Alerts to the user (not your case, but sometimes you want to let them know what went on - certainly if it was an error in updating your server)
change Images (various things)
switch Views
Well, the list is as long as "things you can do in an app", so decide for yourself what you need to mod/update - this is "the" way to do it!
You could also use the UIWebView without ever showing it, like this (Swift 3):
func webView() {
let theWebView: UIWebView
theWebView = UIWebView(frame: UIScreen.main.bounds)
theWebView.delegate = self
if let theURL = URL(string: "your URL") {
let request = URLRequest(url: theURL)
theWebView.loadRequest(request)
}
}
Just don't add it to the view.
The Stack Overflow app detects the name of my jailbrokenly-set default browser (Chrome). How can I achieve the same thing in objective-c and swift?
(Just the name, not the ActivityView code)
Example:
Update: I went into Settings > Stack Exchange and found this:
It looks like the app defaults to Safari, but iff Chrome is installed then links will be sent to that browser. Chrome is most likely detected by the canOpenUrl method described in the answer below.
I suspect that the Stack Exchange app isn't checking for your default browser specifically. After all, since Apple doesn't provide an easy way to change your default browser, I doubt the SDK provides an API to detect the default browser.
Instead, the Stack Exchange app may use the canOpenURL(_:) method on UIApplication to test if a predetermined set of common browser apps are installed. For each browser that is installed, the action sheet gets a new button. That approach could resemble the following code snippet.
let safariURL = NSURL(string: "http://stackoverflow.com")!
let chromeURL = NSURL(string: "googlechrome://stackoverflow.com")!
let operaURL = NSURL(string: "opera-http://stackoverflow.com")!
let sharedApplication = UIApplication.sharedApplication() // convenience
if sharedApplication.canOpenURL(safariURL) {
// add "Safari" button to action sheet
}
if sharedApplication.canOpenURL(chromeURL) {
// add "Chrome" button to action sheet
}
if sharedApplication.canOpenURL(operaURL) {
// add "Opera" button to action sheet
}
// display action sheet