Mail - Add Account screen from UIActivityController - swift

I implemented a simple UIActivityViewController as below
let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
activityController.completionWithItemsHandler = { activityType, completed, returnedItems, activityError in
if let error = activityError where !completed && activityType != nil {
// report the error
}
}
I thought the Add Account screen for Mail could be handled automatically by the UIActivityViewController instance if the user have no mail accounts, but not, it's not doing it.
The first thing I tried was to analyze the completion closure: the activityError instance is nil and the completed value is false. Great, I put this workaround (i want to open from my aap. "settings >> mail >> add account " (the add account page) is it possible.?) whenever this closure with those values is called. But it's called also when the user press Cancel on the mail composer.
So, how do Photos and other not-Apple apps they handle this scenario? Thanks

Seems like Apple doesn't handle well a NSURL type in the activityItems.
I solved it by using absoluteString value of that instance.

Related

How to set local notification content to be the same as the content presented in the home screen when opened? [SWIFT]

I am trying to recreate an existing motivational quote app as practice.
On this app, you get a notification which displays the contents, and if you click it the home page provides you with the rest of the quote (screenshots below). I have seen this type of app a lot – they all use collection views and the notification and homepage content always match.
I have tried mimicking this by setting up local notifications for the next 7 days to provide the user with a random quote from my array:
func configureNotifications() {
let shuffled = quotes.shuffled()
for i in 1...7 {
let content = UNMutableNotificationContent()
content.title = “Daily quotes”
content.body = shuffled[i].text
let alertDate = Date().byAdding(days: i) // scheduled for next 7 days added
var alertComponents = Calendar.current.dateComponents([.day, .month, .year], from: alertDate)
alertComponents.hour = 10
Etc
}
func updateQuoteHome() {
guard let selectedQuote = quotes.randomElement() else {
fatalError("Unable to read a quote.")
}
updateLabels(with: selectedQuote)
}
However, once the notification is clicked, or if the user just randomly opens the app, the content displayed is obviously completely different.
What is the method to link these two together – is it even possible with local notification or are these apps utilising push notifications?
Is there something about this in the documentation?
Thank you ~
You should use Push Notifications for this feature. If you have little or no backend experience you can use Firebase Functions and Firebase Messaging to achieve this.

NSSavePanel Swift not saving

I'm trying to save a file in macOS using Swift. I have the following settings in my app:
In the info.plist I have this key set with a message I need access to the desktop:
Privacy - AppleEvents Sending Usage Description
Though I never see the app make this request.
In my sandbox I have read/write set for User Selected File
I use NSOpenPanel to let the user select a file. The app then programmatically makes changes to the file selected. I display the changes in a textview. I then provide the option for the user to save the changes. This is done with a NSSavePanel and this code:
if let thisFileURL = currentFileURL {
guard let window = view.window else { return }
let panel = NSSavePanel()
panel.directoryURL = FileManager.default.homeDirectoryForCurrentUser
panel.nameFieldStringValue = thisFileURL.lastPathComponent
panel.title = "Saving changes...";
panel.showsResizeIndicator = true;
panel.showsHiddenFiles = false;
panel.canCreateDirectories = true;
panel.allowedFileTypes = ["html"]
panel.beginSheetModal(for: window) { (result) in
if (panel.runModal() == NSApplication.ModalResponse.OK), let saveFileURL = panel.url, let strToSave = self.strCleanContents {
do {
try strToSave.write(to: saveFileURL, atomically: true, encoding: .utf8)
} catch {
self.myAppManager.displayInfoAlert("Unmable to save file:\n\(error.localizedDescription)", self, [], false, response: {(bResponse:Bool) in })
}
}
}
currentFileURL is the URL to the file the user initially selected.
strCleanContents is the edited string from the file the user selected.
When I test this no error is thrown. But nothing happens either. The SavePanel opens, I can navigate to a location, if I select the same location where the original file was located it ask if I want to overwrite the file. Clicking save though does nothing, the panel just sits there. I can't cancel the process, it doesn't close, the file is not written.
beginSheetModal and runModal both display the Save Panel. Call either beginSheetModal to display the panel as a sheet or runModal to display the panel as a window.

Web Text Grabber in Swift

I have been trying to get the text content of any web page via:
func getTextContentFromUrl (url: URL) -> String? {
var content = ""
do {
content = try String(contentsOf: url)
} catch {
return nil
}
return content
}
It works fine if the web page contains texts inside html/body tags, but not if the Web Page contains only javascript, e.g.: https://twitter.com/search?q=tesla&src=typed_query
I know about Swifter, but I cannot program potentially hundreds of API to access any WEB site: twitter, facebook, linkedin, quora, amazon etc. Obviously, WKWebView views know how to display and print their text, therefore I tried to get the text content from WKWebView:
(1) Unfortunately, the following method always returns "" even though I call it from webView(_ webView: WKWebView, didFinish navigation: WKNavigation!):
func getTextContentFromWebView () -> String {
var content = ""
myWKWebView.evaluateJavaScript("document.documentElement") { (string, error) in
if string != nil {
content = string as! String
}
}
return content
}
I tried variants of this code published on the WEB, such as "document.body.textContent", "document.body.innerText", "document.body.outerHTML", "document.body.innerHTML", but this method always returns ""...
(2) I have also tried to use the clipboard to get the text content (myWKWebView.SelectAll(), myWWKWebView.copy()), but myWKWebView.copy() always sends an exception (even though this method is supposed to work for any NSView, as Apple's documentation states):
2020-03-13 15:21:26.251341+0100 Text Miner[7313:603242] -[WKWebView copyWithZone:]: unrecognized selector sent to instance 0x101b815c0
If anyone can manually copy & paste and print the textual content of any web page via any web browser regardless of its content (html/javascript), there should be a generic easy and documented way to grab text from WKWebView, shouldn't be?
I figured out that:
my mistake in the first problem was that myWKWebView.evaluateJavaScript is an asynchronous function, i.e. it returns right away with content="" (without any time to set this variable). The solution is to process the content of the variable "content" inside its body inside the method.
WKwebViews do accept a copy() method but do not implement it: it is up to developers to implement it. I read somewhere that it is done it via an interface javascript-swift...
Anyways, first solution works for me.

Logout sinch user in iOS

I'm working on call/video application. I'm using SINCH SDK and i successfully integrated in swift project and call video work fine but i have a problem that when user is logged out from application still received a notification, i don't know why i used this function to logout
func logOutSinchUser() {
if let client = self._client {
client.stopListeningOnActiveConnection()
client.terminate()
client.unregisterPushNotificationData()
}
self._client = nil
}
Anyone can help me please ?
Please try to unregister the push token first(unregisterPushNotificationDeviceToken if you use sinch managed push) before you terminate the sinch client.
Also use terminateGracefully instead, to give the SDK more time to handle the unregistration process before shut off.
Could be sth like:
func logOutSinchUser() {
if let client = self._client {
client.stopListeningOnActiveConnection()
client.unregisterPushNotificationDeviceToken()
client.terminateGracefully()
}
self._client = nil
}

iOS 10 app crashes when trying to save image to photo library

I'm trying to save an image to the photo library in Swift 3 (I'm working with Xcode 8).
ViewController Code:
func shareImage(image: UIImage) {
let items = [image]
var activityVC: UIActivityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
let excludeActivities: [UIActivityType] = [UIActivityType.airDrop,
UIActivityType.assignToContact,
UIActivityType.addToReadingList,
UIActivityType.copyToPasteboard]
activityVC.excludedActivityTypes = excludeActivities
self.present(activityVC, animated: true, completion: nil)
}
When I run the application, and click on the button to take the screenshot (converting it to image, ..., that's all working perfectly), the app asks for permission to access the photo library, I tap the "OK" button, and then the app crashes. The image is not saved in the photo library.
The only clue I get from Xcode is the following:
2016-09-28 11:24:27.216043 Ajax Kids[4143:1545362] [error] error: -addPersistentStoreWithType:SQLite configuration:(null) URL:file:///var/mobile/Media/PhotoData/Photos.sqlite?readonly_shm=1 options:{
NSPersistentStoreFileProtectionKey = NSFileProtectionCompleteUntilFirstUserAuthentication;
NSReadOnlyPersistentStoreOption = 1;
NSSQLitePersistWALOption = 1;
NSSQLitePragmasOption = {
"journal_mode" = WAL;
};
} ... returned error Error Domain=NSCocoaErrorDomain Code=256 "The file couldn’t be opened." UserInfo={reason=Failed to access file: 1} with userInfo dictionary {
reason = "Failed to access file: 1";
}
2016-09-28 11:24:27.216433 Ajax Kids[4143:1545362] [Migration] Unexpected error opening persistent store <private>, cannot attempt migration <private>)
2016-09-28 11:24:27.216568 Ajax Kids[4143:1545362] [Migration] Failed to open store <private>. Requires update via assetsd (256: <private>)
Does anyone have any idea how to fix this?
Thanks in advance!
UPDATE
Sharing the image on Social Media works fine, so the problem is specified to saving the image in the photo library.
Add new records in your new InfoPlist.strings file.
<key>NSPhotoLibraryAddUsageDescription</key>
<string>$(PRODUCT_NAME)</string>
UPD: iOS 11 key
On iOS 11, there is a new property called NSPhotoLibraryAddUsageDescription, similar to NSPhotoLibraryUsageDescription. See https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html
Try to force request permissions like this:
PHPhotoLibrary.requestAuthorization { status in
if status == .authorized {
//do things
}
}
do not forget import Photos. Hope this helps.
I found the culprit in my particular case. We are using Leanplum for analytics and push notifications. The Leanplum.syncResourcesAsync method was causing the opening of the photo library to crash. It took a couple of days to find as I wasn't aware Leanplum was doing anything to hook into a user's photo library... which in itself is concerning.
We weren't using the functionality this particular method brings, so were able to just remove the method call and the photo library stopped crashing.