INInteraction donation duplicated in Spotlight IOS 12 Beta 5 - swift4

I am donating an INInteraction and everything is working ok, however I can't understand why the donation is showing up duplicated in Spotlight.
Is there a property that needs to be set in order to prevent this??
let viewUsageIntent = UsageIntent()
var susbcribers = [INObject]()
for sub in account.subscribers {
let inObject = INObject(identifier: sub.phoneNumber, display: sub.id)
susbcribers.append(inObject)
}
viewUsageIntent.suggestedInvocationPhrase = phrase
viewUsageIntent.ban = account.ban
viewUsageIntent.subs = susbcribers
let interaction = INInteraction(intent: viewUsageIntent, response: nil)
interaction.donate(completion: {
error in
if let err = error {
MyAppServices.Logger.error(tag: "UsageIntentDonation", message: "Donation for ban \(account.ban) could not be completed: \(err.localizedDescription)")
}
})
Anybody dealing with this issue?. Thanks.

This is not a bug. This is the default behaviour when you set your simulator or iPhone to display recent shortcuts in the developer section. I was just confused by it.
Is not a duplication, it is just displaying the newest one over older ones for development sake

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.

Got an error when dragging files using NSEvent. (macOS)

I wanna drag files to my window and then perform actions.
I tried to use snippets below provided in this answer to distinguish whether you're dragging a file or a window.
// In my window controller
class MyWindowController: NSWindowController {
init() {
// Some initialization steps below are omitted
let win = NSWindow(...)
super.init(window: win)
let contentView = DropView(frame: win.frame)
win.contentView?.addSubview(contentView)
registerGlobalMouseEvent()
}
func registerGlobalMouseEvent() {
self.window?.acceptsMouseMovedEvents = true
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// Codes below will cause errors
let pasteBoard = NSPasteboard(name: .drag)
guard let fileNames = pasteBoard.propertyList(forType: .init(rawValue: "NSFilenamesPboardType")) as? NSArray else { return }
let changeCount = pasteBoard.changeCount
if fileNames.count > 0 && lastChangeCount != changeCount {
lastChangeCount = changeCount
// My actions when dragging
}
})
}
}
Then I ran my codes and started dragging, I got three errors:
[sandbox] Failed to get a sandbox extension
[Framework] Failed to issue sandbox extension for /Users/roy/Downloads/test.txt with error 1
[default] Failed to issue sandbox token for URL: 'file:///Users/roy/Downloads/test.txt' with error: 'Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedDescription=Cannot issue a sandbox extension for file "/Users/roy/Downloads/test.txt": Operation not permitted}'
 
But when I just do
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// My actions
})
, then everything went fine.
 
The first error seems harmless since it didn't prevent my app from running.
The second and the third ones are deadly and directly caused my app to crash.
I wonder if there are any problems in his code? Any useful thoughts would be great! :)
 
You need to know about Bookmarks and Security Scoped URLs when working with sandbox . A dragged URL gives your app process permission just once to read or read/write a “user selected file” depending on how you configure entitlements.
You can save a bookmark (blob of data) to keep access over subsequent sessions as long as the file isn’t updated by another process at which point the bookmark becomes stale and you will need to encourage the user to select the file again.
Handing a URL to another process across an XPC boundary like sharing requires that you own the file so may involve a copy to your sandbox cache.
e.g:
let dragurl = url_of_dragged_file //at this point you have at-least read access
let cachepath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last!
let cachedir = URL(fileURLWithPath: cachepath)
let cacheurl = cachedir
.appendingPathComponent(UUID().uuidString)
.appendingPathExtension(dragurl.pathExtension)
try FileManager.default.copyItem(at: dragurl, to: cacheurl)
At this point you have a copy in your local sandbox cache that can be handed off to a share sheet.
So I finally got a solution for this. :)
It appears that it indeed have something to do with the snippets I mentioned above, and here's the correction:
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
let pasteboard = NSPasteboard(name: .drag)
let changeCount = pasteboard.changeCount
if lastChangeCount != changeCount {
lastChangeCount = changeCount
if pasteboard.canReadObject(forClasses: [NSURL.self], options: [:]) {
/// actions
}
}
})
In this way, I got no errors and my codes run perfectly!

Swift Realm issue in iOS 14+

------LE: We ended up removing the encryption of the database because with realm team suggestions it got worse - all we could do was to remove the database and loose all stored info. Now we encrypt in keychain only the fields we need.------
I have an app released in store and after updating their iOS version to 14+, users started to complain about info not being populated from database. Not all users with iOS 14+ have this issue, it appears randomly on some devices.
The issue goes away for awhile if they reinstall the app or after they update it to another version, but after using it for a few minutes it happens again.
My database uses encryption as documented here.
The store version of my app uses Realm 5.4.8, but I tested their last version (10.0.0) and the issue is still present.
I checked this issue but it's not the case for me, I don't have a shared app group container or a share extension.
Here's how the initialisation of realm looks like:
override init() {
super.init()
do {
guard let config = getMigrationAndEncryptionConfiguration() else {
realmConfigured = try Realm()
return
}
realmConfigured = try Realm(configuration: config)
} catch let error as NSError {
// this is where I got the error:
//"Encrypted interprocess sharing is currently unsupported.DB has been opened by pid: 4848. Current pid is 5806."
}
}
func getMigrationAndEncryptionConfiguration() -> Realm.Configuration? {
let currentSchemaVersion: UInt64 = 19
if Keychain.getData(for: .realmEncryptionKey) == nil {
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { bytes in
SecRandomCopyBytes(kSecRandomDefault, 64, bytes)
}
Keychain.save(data: key, for: .realmEncryptionKey)
}
guard let key = Keychain.getData(for: .realmEncryptionKey) else {
return nil
}
let fileUrl = Realm.Configuration().fileURL!.deletingLastPathComponent()
.appendingPathComponent("Explorer.realm")
var config = Realm.Configuration(fileURL: fileUrl,
encryptionKey: key,
schemaVersion: currentSchemaVersion, migrationBlock: { (migration, oldVersion) in
if oldVersion != currentSchemaVersion {
print("we need migration!")
}
})
return config
}
I had another question opened for the same issue on SO, but it was closed because I didn't have enough details. After another release of my app with more logs, I could find the error that appears at initialisation of realm:
"Encrypted interprocess sharing is currently unsupported.DB has been opened by pid: 4848. Current pid is 5806. "
This appears after the app goes to background, it gets terminated (crash or closed by the system/user) and when the users opens it again, realm fails to init.
I read all about encrypted realm not being supported in app groups or in a share extension, but I didn't implement any of that in my app, is there any other reason why this error happens?
I also removed Firebase Performance from my app because I read that this module could generate issues on realm database, but it didn't help.
I opened an issue on realm github page, but I got no answer yet.
Does anyone have any idea how to fix this or why is this happening?
Thank you.

'UIPastebaord.general.hasStrings' not working on iOS 14.0

I'm offering a custom keyboard app.
I am checking'full access' with the code below to activate some functions. It's a valuable code I discovered through this site a few years ago. But I found out that the code below doesn't run on iOS 14.
UIPasteboard.general.hasStrings always returns false. hasImages/hasColors/hasURLs all return false. But it doesn't seem to be real. If you paste, there is a previously copied content or only ‘TEST’ is pasted.
'TEST' is for checking purposes and should not be printed.
let pasty = UIPasteboard.general
if pasty.hasURLs || pasty.hasColors || pasty.hasStrings || pasty.hasImages {
hasFullAccess = true
} else {
pasty.string = "TEST"
if pasty.hasStrings {
hasFullAccess = true
pasty.string = ""
}
}
I am deeply reflecting on what I only found out about this. Also, I'm really sorry for the users who use my app. So I'm asking here because I want to solve it somehow. So, if anyone knows how to fix it, I'd like to let you know.
What I have done so far
Update ‘firebase’ and ‘realm’ to the latest version with ‘cocoapod’
Fix a problem after pod update
Try modifying the code continuously by turning on/off Allow Full Access in iOS settings
Google search…
Let me know if someone knows a better solution. Or, I'd like to give you a clue as to the cause of the problem. I hope that people who have the same problem will consider it together.
Thanks for reading this far. And I'll wait for someone's help. please.
We found the same issue. Our current solution is to use viewWillAppear instead of viewDidLoad when checking for full access.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// We need to check fullAccess after view has appeared in order for UIPasteboard to be available.
if self.hasFullyAccess() == false {
// Do whatever.
}
}
public func hasFullyAccess() -> Bool {
var hasFullAccess = false
if #available(iOS 10.0, *) {
let pasty = UIPasteboard.general
if pasty.hasURLs || pasty.hasColors || pasty.hasStrings || pasty.hasImages {
hasFullAccess = true
} else {
// We test if we can put something in UIPasteboard, if anything we have access.
pasty.string = "TEST"
if pasty.hasStrings {
hasFullAccess = true
pasty.string = "" // Removes string from pasty again.
}
}
}
return hasFullAccess
}

The "prefs" URL Scheme is not working in iOS 10 (Beta 1 & 2)

I can't get the "prefs" URL Scheme to work in iOS 10 (Beta 1).
It's set up correctly since the same App works fine on iOS 9.
Is this a bug or did it get renamed / removed?
Code:
let settingsUrl = NSURL(string: "prefs:root=SOMETHING")
if let url = settingsUrl {
UIApplication.sharedApplication().openURL(url)
}
Update: (Beta 2)
Still not working in Beta 2.
It seams to be an bug. For example if you want do invite someone using GameCenter in iOS 10 and you're not logged into iMessage, you'll get a popup asking you to log in. But the "Settings" button does absolutely nothing.
Just replace prefs to App-Prefs for iOS 10
Below code works for iOS 8,9,10
Swift 3.0 and Xcode >= 8.1
if #available(iOS 10.0, *)
{
UIApplication.shared.openURL(URL(string: "App-Prefs:root=SOMETHING")!)
}
else
{
UIApplication.shared.openURL(URL(string: "prefs:root=SOMETHING")!)
}
Swift 2.2
if #available(iOS 10.0, *)
{
UIApplication.sharedApplication().openURL(NSURL(string:"App-Prefs:root=SOMETHING")!)
}
else
{
UIApplication.sharedApplication().openURL(NSURL(string:"prefs:root=SOMETHING")!)
}
Works for me.
Happy Coding 😊
You can use UIApplicationOpenSettingsURLString to open your own app's settings (this has been available since iOS 8) but any other prefs: URL is now considered a private API and use will result in app rejection.
You can use Prefs:root=SOMETHING
iOS 10 updated URL Scheme for Settings, you need to upcase the "p".
Ref: https://github.com/cyanzhong/app-tutorials/blob/master/schemes.md
NOTICE: It only works on Widgets, not works in Apps. (iOS 10.0.2)
#Saumil Shah's solution works in App, is more useful.
For the record, for Location services App-Prefs:root=Privacy&path=LOCATION worked for me. When I tested on a device and not a simulator.
I won't list the things I tried that did not work, it's a long list.
Usage example that assumes either location services are disabled or permission is denied or not determined:
if !CLLocationManager.locationServicesEnabled() {
if let url = URL(string: "App-Prefs:root=Privacy&path=LOCATION") {
// If general location settings are disabled then open general location settings
UIApplication.shared.openURL(url)
}
} else {
if let url = URL(string: UIApplicationOpenSettingsURLString) {
// If general location settings are enabled then open location settings for the app
UIApplication.shared.openURL(url)
}
}
This is not available on iOS 11, we can just open Settings like:
if let url = URL(string:UIApplicationOpenSettingsURLString) {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
If anyone is interested in a "gray area" API, you can use:
//url = "prefs:root=SOMETHING"
[[LSApplicationWorkspace defaultWorkspace] openSensitiveURL:url withOptions:nil];
This will give you what you want. Hide it well, and it works in iOS 10.