WatchKit: Speech to text conversion in WatchKit Apps - iphone

Can any one help me with a sample code for adding Speech to Text conversion feature in Apple Watchkit apps.

Yes, it's possible. Here is the documentation:
https://developer.apple.com/library/prerelease/ios/documentation/WatchKit/Reference/WKInterfaceController_class/index.html#//apple_ref/occ/instm/WKInterfaceController/presentTextInputControllerWithSuggestions:allowedInputMode:completion:
The code look like this. You provide a suggestions array with words (or emoji too) and you set the allowed input mode that can accept animated emoji, emoji or plan text only.
[self presentTextInputControllerWithSuggestions:#[#"hello", #"world"] allowedInputMode:WKTextInputModePlain completion:^(NSArray *results) {
NSLog(#"results: %#", results);
}];
The result is this:

You can ask for user input and give him suggestion (see Swift example bellow).
self.presentTextInputControllerWithSuggestions(["suggestion 1", "suggestion 2"] allowedInputMode: .Plain, completion: { (answers) -> Void in
if reply && reply.count > 0 {
if let answer = answers[0] as? String {
println("\answer")
}
}
})
If suggestion is nil it goes directly to dictation. It is not working on the simulator but it is on real watch.

self.presentTextInputControllerWithSuggestions(["Y","N"], allowedInputMode: WKTextInputMode.Plain,
completion:{(results) -> Void in
let aResult = results?[0] as? String
print(aResult)
})

Related

Set `selected text` through the macOS Accessibility APIs in Catalyst apps

Not sure if it's a bug or what. I made an app that add Vim bindings all over macOS, but it fails in Catalyst apps. The text is readable mostly—although line numbers are wrong and line ranges too—but I can't set the selected text. It does nothing expect selecting the text, but not replacing it with the new one. It works well in all native apps that support the Accessibility.
Am I doing things wrong or is this a confirmed bug? (I've been reporting bugs in the Accessibility API for two years, with no change from Apple's part.)
The code is fairly simple. As an example:
func ....() {
var selectedTextRange = CFRange()
selectedTextRange.location = 2
selectedTextRange.length = 3
let newValue = AXValueCreate(.cfRange, &selectedTextRange)
guard AXUIElementSetAttributeValue(axFocusedElement, kAXSelectedTextRangeAttribute as CFString, newValue!) == .success else { return false }
guard AXUIElementSetAttributeValue(axFocusedElement, kAXSelectedTextAttribute as CFString, "hehe" as CFTypeRef) == .success else { return false }
return true
}
The func returns true. But in Catalyst apps there's a selection from location 2 to 5, but the text is not replaced by "hehe".
I've got an Xcode project also that shows the issue: https://github.com/godbout/AXBugsWithCatalystApps
Thanks.

Swift Firebase Authentication - two questions about error handling (I'm not sure how to name these errors)

It's really hard to find a proper title for this question. Please be easy on me.
The first part is a check to see if an account exists:
Auth.auth().fetchSignInMethods(forEmail: userEmail, completion: {
(providers, error) in
if error != nil {
self.displayAlertMessage(alertTitle: "Unhandled error", alertMessage: "Undefined error #SignUpViewController_0001");
return;
} else if providers != nil {
self.displayAlertMessage(alertTitle: "Error", alertMessage: "This account is not exist.");
return;
}
})
As you can see, I have something named Unhandled error with message Undefined error. I don't know how to name it properly. Can somebody explain that part to me?
The second one is about getting a localized string - any ideas to make it fancy?
Auth.auth().createUser(withEmail: userEmail, password: userPassword) { user, error in if error == nil && user != nil {
self.displayAlertMessage(alertTitle: "Success", alertMessage: "Your account created successfully. We send you a verification email.", dismiss: true);
} else {
self.displayAlertMessage(alertTitle: "Firebase error", alertMessage: "(error!.localizedDescription)");
}
}
Thanks for tips :)
You can handle the Errors this way:
Auth.auth().fetchSignInMethods(forEmail: email, completion: { (response, error) in
if let error = error, let errCode = AuthErrorCode(rawValue: error._code)
{
switch errCode {
case .emailAlreadyInUse:
GeneralHelper.sharedInstance.displayAlertMessage(titleStr: LocalizeConstant.CommonTitles.Alert.rawValue.localizedStr(), messageStr: LocalizeConstant.CommonTitles.Continue.rawValue.localizedStr())
case .accountExistsWithDifferentCredential:
GeneralHelper.sharedInstance.displayAlertMessage(titleStr: LocalizeConstant.CommonTitles.Alert.rawValue.localizedStr(), messageStr: LocalizeConstant.CommonTitles.Continue.rawValue.localizedStr())
default:
break
}
return
}
}
Here I am getting the errCode using AuthErrorCode provided by Firebase itself and then, I am passing in the received error code using error._code. So, now I can get the type of AuthErrorCode. Using this I am making cases like .emailAlreadyInUser, .accountExistsWithDifferentCredential etc. You can just type . and it will show you all the AuthErrorCodes. So, you can simply handle the error codes in this way.
Now, coming to the second part of the question, i.e. getting localized string. You can add localization to Firebase, for that you have to select the language code. Auth.auth().languageCode = "en" //For English. But, I do not think that it gives localized errors as there are many more languages than what Firebase supports. This mainly for sending localized emails.
To handle the localization, you have to create your own method as I did. You can see that I have called a function displayAlertMessage in which I am passing thetitleStr: LocalizeConstant.CommonTitles.Alert.rawValue.localizedStr(), which is a part of localization.
struct LocalizeConstant {
enum CommonTitles: String
{
case Alert = "common_alert"
}
}
This value designates to the key given by me in the localization file. If you do not know about localization, you have to do a Google search on it. Let's say I have two Localizable.strings one is in English and the other one is in French. In Localizable.strings(English), I've written Alert like this:
"common_alert" = "Alert";
And, In French:
"common_alert" = "Alerte!";
So, this is how I have manually added localization in my app. But, to achieve this you have to do two things. 1) You have to set up your appLanguage. 2) You have to call a method which will fetch the values from these keys defined in the Localizable.strings file.
To do this, I have created a method localizedStr(). It is an extension to String and you can use it as follows.
extension String{
func localizedStr() -> String
{
var finalRes = ""
if let path = Bundle.main.path(forResource: Constants.appLang, ofType: "lproj") //Constants.appLang is "en" here for "English", but you can set accordingly.
{
if let bundle = Bundle(path: path)
{
finalRes = NSLocalizedString(self, tableName: nil, bundle: bundle, value: " ", comment: " ")
}
}
return finalRes
}
}
Now, this method localizedStr() will give you a localized string according to your app language. Even, if Firebase provides localized error codes(which I think it does not), it is impossible to get the error description in each language. So this is the best way I came up with. It may not be the best method out there in the world, but it does the task.
P.S.: To optimize this throughout the app, either you can create an extension to AuthErrorCode or you can create a Helper function where you will just pass the error._code and it will return the localized string. I've added the long way so that you can understand everything in the best way.

MacOS NSWorkspace.shared.open "The application can’t be opened. -50"

Following some other Stack Overflow code examples of NSWorkspace.shared.open(), I came up with this:
#IBAction func mailFileVacuum(_ sender: NSButton) {
let receiver = sender.alternateTitle
let sendAddress = String(format: "mailto:%##filevacuum.com?subject=FileVacuum %#", receiver, receiver).addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
NSLog("receiver %#", receiver)
let mailUrl = URL(string: sendAddress)
NSLog("mailUrl %#", mailUrl!.absoluteString)
if NSWorkspace.shared.open(mailUrl!) {
print("Default browser was successfully opened to send email. 😊📬")
}
}
☝️ that gets us this 👇
I tried changing the default browser, that's not the issue.
NSLog(mailUrl) logs this mailto%3AFeedback%40filevacuum.com%3Fsubject=FileVacuum%20Feedback
Look good maybe 🤔...
¿Que Paso?
You should not be percent encoding the entire URL; but rather, its individual components. See the Apple URL Scheme Reference.
The correctly formatted URL should look like (i.e. NSLog(mailUrl) should output):
mailto:Feedback#filevacuum.com?subject=FileVacuum%20Feedback

How to print the current local network name in swift

I am creating an iOS app which displays the current local network name at the top of the screen, and so forth. I am trouble-shooting different ways to display this but I can't manage the current program. Can someone help me out?
I've looked at several GitHub, stack overflow, and youtube comments about this, but nome of them worked.
In the current Xcode I'm using which is Xcode(10.4.2) I'm using a label(correct me if I should use something else) to display the current Wifi named --> (WiFi: ......)
Please don't test on the simulator, use the iphone for testing.
Import SystemConfiguration :
import SystemConfiguration.CaptiveNetwork
In ViewDidLoad :
let wifiName = getWiFiName()
print("Wifi: \(String(describing: wifiName))")
Function :
func getWiFiName() -> String? {
var serviceSetIdentifier:String?
if let interfaces = CNCopySupportedInterfaces() as Array? {
interfaces.forEach { interface in
guard let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? else { return }
serviceSetIdentifier = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
}
}
return serviceSetIdentifier
}

How do you copy text from a text view with a different font and when pasted on other apps like messages, it's the same font?

This line to just copy the text itself without font and paste it works:
pasteBoard.string = MainController.customTextView.text
I've tried looking at similar answers that people asked about this question but almost every answer I see is in Objective C and outdated. By looking at other answers like this I think I got the copy working but when I paste the copied text, it doesn't paste anything. Here's what I have for my copy function:
#objc func handleCopyButton() {
MainController.customTextView.resignFirstResponder() // dismiss keyboard
// Setup code in overridden UITextView.copy/paste
let selectedRange = MainController.customTextView.selectedRange
let selectedText = MainController.customTextView.attributedText.attributedSubstring(from: selectedRange)
// UTI List
let utf8StringType = "public.utf8-plain-text"
let rtfdStringType = "com.apple.flat-rtfd"
// Try custom copy
do {
// Convert attributedString to rtfd data
let fullRange = NSRange(location: 0, length: selectedText.string.count)
let data:NSData? = try selectedText.data(from: fullRange, documentAttributes: [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.rtfd]) as NSData
if let data = data {
// Set pasteboard values (rtfd and plain text fallback)
pasteBoard.items = [[rtfdStringType: data], [utf8StringType: selectedText.string]]
}
} catch { print("Couldn't copy") }
// Copy if custom copy not available
MainController.customTextView.copy()
}
Let me know if you have any questions on this. Thank you in advance!
Edit: For what I was trying to do, it turns out you can't copy and paste fonts (at least on iOS but in MacOS I believe you can), but what you could do is copy and paste unicode characters that looks like different fonts. Check this solution out if it's something you're interested in.
This simply would not work on messages since apple only uses system fonts for messages.
In order for this to work on other apps they have to support it and have the font available to them, if on iOS the app itself has to have the font installed.
If you want your text to appear then you could use UIPasteboard.general.string = stringVar
Try some of the recommendations from this stackoverflow question.