UIDocumentInteractionController presentOpenInMenuFromBarButtonItem stopped working well on iOS8.1 - cocoa-touch

My app has a document interaction controller which is used to open documents in other apps.
The following code displays a button that opens the 'Open in' menu and allows the user to open the file in other apps – i.e. Send it by mail if the user chose the mail app in the 'Open in' menu, the mail app creates a new email and automatically attaches the file to the mail body.
The following code worked fine in iOS7 but stopped working well on iOS8+. Files are not being attached to mails and I get an error log message.
Declaration for UIDocumentInteractionController:
#property (nonatomic, strong) UIDocumentInteractionController* interactionController;
Initialization:
self.interactionController = [UIDocumentInteractionController interactionControllerWithURL:self.url];
self.interactionController.delegate = self;
self.interactionController.name = self.file.name;
The call for the 'Open in' menu:
[self.interactionController presentOpenInMenuFromBarButtonItem:self.openInBarButtonItem animated:YES];
Example for error message received after opening an excel file:
Unknown activity items supplied: (
{
"com.microsoft.excel.xls" = <504b0304 ....000000>;
},
"" )
viewServiceDidTerminateWithError: Error
Domain=_UIViewServiceInterfaceErrorDomain Code=3 "The operation
couldn’t be completed. (_UIViewServiceInterfaceErrorDomain error 3.)"
UserInfo=0x… {Message=Service Connection Interrupted} (lldb).
I would appreciate any ideas to fix this issue.
Thanks,
Ori

Here is my Code
BOOL IOS8=SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0");
if (IOS8){
if ([interactionController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES]) {
NSLog(#"menu is presented");
}

Related

Sparkle shows popup "App up to Date" every time on launch if app is in latest version

I'm using Sparkle with Go App.
sparkle.m :
#import <Headers/SUUpdater.h>
static SUUpdater* updater = nil;
void sparkle_checkUpdates()
{
if (!updater) {
updater = [[SUUpdater sharedUpdater] retain];
}
[updater setUpdateCheckInterval:3600];
[updater checkForUpdates:updater];
}
main.go :
func main() {
sparkle.Sparkle_checkUpdates()
// Some blocking call
}
I uploaded an appcast.xml file and Sparkle is working fine, the update is detected properly.
But after updating, on every startup of the app, an 'up to date' popup shows up :
I want this message to not show up. Popup should be shown only if an update is available.
For this I tried replacing
[updater checkForUpdates:updater];
with
[updater checkForUpdatesInBackground];
but now Sparkle doesn't work even if there's an update. No Popup shows up.
What am I missing here ?
Thanks for any help!

Permission to take photo OR get image from library not shown in iOS9 (Xcode 7beta, Swift2)

The code below shows an example for my access to the image lib. No matter where I call the code (view) I do not see the permission dialog from the phone popping up and therefore cannot allow my app to access either camera or library.
Also, the privacy settings do not show my app either. Any thoughts? I'm going nuts.
let imgPicker = UIImagePickerController()
imgPicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
imgPicker.modalPresentationStyle = UIModalPresentationStyle.Popover
self.presentViewController(imgPicker, animated: true, completion: nil)
another way I tried
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
let imagePicker:UIImagePickerController = self.imagePickerController
imagePicker.allowsEditing = true
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureMode.Photo
imagePicker.cameraDevice = UIImagePickerControllerCameraDevice.Rear
imagePicker.showsCameraControls = true
imagePicker.navigationBarHidden = true
imagePicker.toolbarHidden = true
imagePicker.delegate = self
self.presentViewController(imagePicker, animated: true, completion: nil)
}
You need to set a new pair of Info.plist values, same as the String for Location Services would be in iOS8:
Just set your description string for those.
Check info.plist.
if "Bundle display name" set as nothing,
At iOS 8.1 will popup permission window like this
"" Would Like to Access Your Photos
But at iOS 9, there is no popup permission at all.
Also, no permission setting, at Setting > Privacy > Photos > Your app name.
To solve this,
Remove "Bundle display name" in your info.plist.
Apparently this appears to be an issue with iOS9. For some reason the permission access dialog does not pop up. I have successfully tested on iOS8, using the same code.

Dropping files onto the app's dock icon works except for proxy icons

I want to be able to accept drops on my app's dock icon from files, URLs, and text. Since files (public.file-url) are a subtype of URL (public.url), I added just two Services entries to my Info.plist:
Services
Item 0 (processURL)
Instance method Name = processURL
Send Types
Item 0 = public.url
Menu
Menu item title = Process URL
Item 1 (processString)
Instance method Name = processString
Send Types
Item 0 = public.plain-text
Menu
Menu item title = Process Text
Then I made my -applicationDidFinishLaunching call [NSApp setServicesProvider: self], and wrote a couple methods (-processString:userData:error and -processURL:userData:error) there in my application delegate. The app icon now accepts drops of all three types. In the -processURL:... method, it's easy to check if it's a local file or not, so that handles both of those cases.
One case still eludes me, though. When I try dragging a window's proxy icon to the app, it highlights the icon as if it can accept the drop, but then my method isn't called.
I tried dropping proxy icons from Xcode, Terminal, Preview, and some third-party apps: none would call my services method. But strangely, a proxy icon dropped from the Finder worked fine.
I tried changing public.url to public.item (the base type of the physical hierarchy), but my method is still not called for non-Finder proxy icons.
When the Finder successfully drops a proxy icon on my app, the pboard -types it provides are:
"public.file-url",
"CorePasteboardFlavorType 0x6675726C",
"dyn.ah62d4rv4gu8y6y4grf0gn5xbrzw1gydcr7u1e3cytf2gn",
NSFilenamesPboardType,
"dyn.ah62d4rv4gu8yc6durvwwaznwmuuha2pxsvw0e55bsmwca7d3sbwu",
"Apple URL pasteboard type"
I tried using each of these directly as the "Send Types". "public.file-url" and "NSFilenamesPboardType" highlight the icon as if it'll accept the drop, but don't. The others, unsurprisingly, don't even highlight the dock icon.
I can't find any reference to proxy icons having a different UTI than normal files. Do they? That would be weird.
I know this must be possible, because I can drag proxy icons from any window onto a Terminal window. What am I missing?
UPDATE: From an NSView, if I -registerForDraggedTypes including "public.url", I do get drops of proxy icons from all apps, with exactly the same -types list as from the Finder, listed above. So it's clearly something special to receiving drops via the dock icon. This should still be possible somehow: you can drag a proxy icon from a (non-Finder) window (e.g., an .xcworkspace from Xcode) onto the Terminal dock window, and it catches that just fine.
Swift 4 for your app delegate
func application(_ sender: NSApplication, openFile: String) -> Bool {
Swift.print("sender \(sender) file \(openFile)")
return true
}
func application(_ sender: NSApplication, openFiles: [String]) {
Swift.print("sender \(sender) list \(openFiles)")
// Create a FileManager instance
let fileManager = FileManager.default
for path in openFiles {
do {
let files = try fileManager.contentsOfDirectory(atPath: path)
for file in files {
_ = self.application(sender, openFile: file)// void return
}
}
catch let error as NSError {
print("Yoink \(error.localizedDescription)")
}
}
}
If you implement dragging files to your dock icon using application:openFile: in your NSApplicationDelegate, then dragging proxy icons should work too. The trick to accepting all files is adding a Document Type with extensions of '*'.

Accessing the Thunderbird message when closing a message tab / window

We have developed a Thunderbird (11) plugin that allows us to save the content of a message to disk. Now we are extending this extension to allow automatic processing of a message when you close it. We run into a number of issues:
We cannot find a way to hook into a 'close tab' event. We are also having trouble getting the Message URI of the currently open tabs (we are trying catching click and keyboard events now). This information does not appear to be available in the DOM of the tab container.
Is there a way to detect closing of a mail message tab or window in a generic way, together with retrieving the URI of the closed mail message for further processing?
We have looked at the documentation of the tab container, the NsIWindowMediator, tried various event listeners, but no luck so far.
Edit: We are getting some results using the most recently closed tabs list. Not a very elegant solution but at least we have a reference to the tab. Now we only have to get the URI to the message that was contained inside the tab.
We cannot find a way to hook into a 'close tab' event.
The (badly documented) <tabmail> element allows registering tab monitors. Something like this should work:
var tabmail = document.getElementById("tabmail");
var monitor = {
onTabClosing: function(tab)
{
...
}
};
tabmail.registerTabMonitor(monitor);
We are also having trouble getting the Message URI of the currently open tabs
The <tabmail> element has a property tabInfo containing information on the currently open tabs. You probably want to look only at the tabs where mode.name is "message" (there is a bunch of other modes as well, e.g. "folder" or "contentTab"). This mode has a getBrowser() method, so something like this should do:
var tabmail = document.getElementById("tabmail");
for (var i = 0; i < tabmail.tabInfo.length; i++)
{
var tab = tabmail.tabInfo[i];
if (tab.mode.name == "message")
alert(tab.mode.getBrowser().currentURI.spec);
}
Edit: As Peter points out in the comments, the approach to get the URI for a message will only work the currently loaded message - all tabs reuse the same browser element for the mail messages. Getting the URI properly is more complicated, you have to get the nsIMsgDBHdr instance for the message via TabInfo.folderDisplay.selectedMessage and then use nsIMsgFolder.getUriForMsg() to construct the URI for it:
var tabmail = document.getElementById("tabmail");
for (var i = 0; i < tabmail.tabInfo.length; i++)
{
var tab = tabmail.tabInfo[i];
if (tab.mode.name != "message")
continue;
var message = tab.folderDisplay.selectedMessage;
alert(message.folder.getUriForMsg(message));
}
For the second part of the question:
The following example code will at provide you the msgDBHdr objects of all opened tabs. You should do some checks on the type to avoid accessing a message in a calendar tab.):
tabInfos = window.document.getElementById("tabmail").tabInfo;
for (i = 0; i < tabInfos.length; i++) {
msgHdr = tabInfos[i].folderDisplay.selectedMessage;
alert(
msgHdr.mime2DecodedSubject+"\n"
+msgHdr.messageId+"\n"
+"in view type "+tabInfos[i].mode.type
);
}
The tabinfo entries have some further interesting information. Just open the ErrorConsole and run
top.opener.window.document.getElementById("tabmail").tabInfo[0].toSource()
and read through it carefully.

Getting Safari document title/location with Scripting Bridge does not work in full-screen mode

I'm trying to get the URL and document title from the topmost Safari document/tab. I have an AppleScript and an objective-c version using Apple's Scripting Bridge framework.
Both versions work fine for most web pages, however when I open a Youtube video in full-screen mode, the Scripting Bridge based version fails. The Apple Script works fine for "normal" and full-screen Safari windows.
Can anyone see what is wrong with the Scripting Bridge code below to cause it to fail for full-screen Safari windows?
Here the code (I omitted error checking for brevity):
AppleScript:
tell application "Safari"
# Give us some time to open video in full-screen mode
delay 10
do JavaScript "document.title" in document 0
end tell
Scripting Bridge:
SafariApplication* safari = [SBApplication applicationWithBundleIdentifier:#"com.apple.Safari"];
SBElementArray* windows = [safari windows];
SafariTab* currentTab = [[windows objectAtIndex: 0] currentTab];
// This fails when in full-screen mode:
id result = [safari doJavaScript: #"document.title" in: currentTab];
NSLog(#"title: %#", result);
Scripting Bridge error (with added line breaks):
Apple event returned an error. Event = 'sfri'\'dojs'{
'----':'utxt'("document.title"),
'dcnm':'obj '{ 'want':'prop',
'from':'obj '{ 'want':'cwin',
'from':'null'(),
'form':'indx',
'seld':1 },
'form':'prop',
'seld':'cTab' }
}
Error info = {
ErrorNumber = -1728;
ErrorOffendingObject = <SBObject #0x175c2de0:
currentTab of SafariWindow 0 of application "Safari" (238)>;
}
I could not find details about the given error code. It complains about 'currentTab' which shows that the JavaScript event at least made it all the way to Safari. I assume that the current tab receives the event, but refuses to run the JS code, because it is in full-screen mode. However, why does this work for an AppleScript? Don't they use the same code path eventually?
Any suggestions are greatly appreciated. Thanks!
This appears to be a failure in the header file created by sdef/sdp--your Objective-C does not parallel your working AppleScript (and the header file seemed to indicate that there is no doJavaScript:in: that would work on a document, as in your AppleScript). When I used the following code, which does parallel your AppleScript, it gave the title without error even for a full-screen YouTube video. The cast from SafariDocument* to SafariTab* in order to use doJavaScript:in: feels wrong, but seems to work.
SafariApplication* safari = [SBApplication applicationWithBundleIdentifier:#"com.apple.Safari"];
SBElementArray* documents = [safari documents];
SafariDocument* frontDocument = [documents objectAtIndex: 0];
// This *no longer* fails when in full-screen mode:
id result = [safari doJavaScript: #"document.title" in: (SafariTab *) frontDocument];
NSLog(#"title: %#", result);
tell application "Safari"
get URL of current tab of front window
end tell
The Objective-C is then simply
SafariApplication* safari = [SBApplication
applicationWithBundleIdentifier:#"com.apple.Safari"];
for (SafariWindow *window in safari.windows) {
if ([window visible]) {
result = window.currentTab.URL;
break;
}
}