NSDocument-based app, open dialog with 'New Document' button on launch - objective-c

TextEdit and Pixelmator both open an open-file-dialog on launch that has a 'New Document' button in the bottom left corner.
Is there any particular code available to achieve the very same effect?
The reason I ask is that Pixelmator's way of going about it, the 'New Document' button included, is exactly the same as TextEdit, and I figure there must be some simple way to achieve this but I must be missing it.

Turns out you need to enable iCloud.

I found that adding an empty accessoryView to the openPanel also makes the "New Document" button visible. To do this, in your NSDocumentController descendant override beginPanel:forTypes:completionHandler: for example like below
- (void)beginOpenPanel:(NSOpenPanel*)openPanel forTypes:(NSArray<NSString*>*)inTypes completionHandler:(void(^)(NSInteger result))completionHandler {
// adding any accessory view makes the "New Document" button visible.
NSView* workaround = [[NSView alloc] initWithFrame:NSZeroRect];
openPanel.accessoryView = workaround;
// for non-arc: [workaround release];
[super beginOpenPanel:openPanel forTypes:inTypes completionHandler:^(NSInteger result) {
openPanel.accessoryView = nil;
completionHandler(result);
}];
}
You'll get warnings like this in the log:
[Layout] The Open/Save panel was supplied an accessory view with bad layout constraints, resulting in a view that is zero width. ...
I have not found a way to avoid that, but at least the New Document button is visible and working OK.

Related

iOS 8 UINavigationController disable Back Button

in my Navigation Controller I need to temporarily disable the back button. I know that it can be hidden using the following or something similar:
[self.navigationController.navigationItem setHidesBackButton:YES animated:YES];
But that is not what I need, instead I want the back button to be greyed out and non-responsive to user touch events. Is their a way to achieve this without replacing the default back button?
Thanks in advance!
To disable the back button, these commands would make it do what you want it to do:
Enable:
self.navigationController.navigationBar.userInteractionEnabled = YES;
self.navigationController.navigationBar.tintColor = [UIColor blueColor];
Disabled:
self.navigationController.navigationBar.userInteractionEnabled = NO;
self.navigationController.navigationBar.tintColor = [UIColor lightGrayColor];
Update:
As of iOS 7, there's also a swipe that you'll want to disable on the UINavigationBar.
// You wrap it an 'if' statement so it doesn't crash
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
// disable the interactivePopGestureRecognizer
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
This hides the back button, so it becomes unreachable for the user. And it disables the swipe gesture.
[self.navigationItem setHidesBackButton:YES animated:YES];
Swift:
navigationItem.setHidesBackButton(true, animated: true)
See more info in Apple's documentation.
I know this is quite old but I had this problem too.
In my case in one scenario I had to disable the back button and in another one I had to disable all navigation buttons. my solution was disabling the navigation bar in total in both scenarios:
self.navigationController.view.userInteractionEnabled = NO;
This won't show the buttons as disabled but will prevent touches.
Hope this will help
I believe that following should help:
self.navigationController.navigationItem.backBarButtonItem.enabled = NO;
UPDATE
Sorry guys, my belief didn't come true.
It seems that property backBarButtonItem is designed only for setting custom title or image for Back Button.
From documentation:
If you want to specify a custom image or title for the back button,
you can assign a custom bar button item (with your custom title or
image) to this property instead. When configuring your bar button
item, do not assign a custom view to it; the navigation item ignores
custom views in the back bar button anyway.
The default value of this property is nil.
Unfortunately I didn't find any way of disabling back button with saving its native look and behaviour, because any time when I try to set custom UIBarButtonItem into navigationItem.backBarButtonItem property - it gets updated with appropriate native back button style and it always has enabled == YES.
I think this is done by Apple for a reason because we basically shouldn't force the user to stay on a detail screen and disable him from going back.
Also, in iOS7 and later user always can use swipe-from-left-edge gesture (if you don't disable it) to go back.
The only one ugly thing that I can recommend is to create a custom UIBarButtonItem and set it into leftBarButtonItem with 'Back' title, target and selector which will pop your viewController. By default it will substitute native back button.
Then you can disable it as usual using navigationItem.leftBarButtonItem.enabled = NO.
Unfortunately it will not look and act (in case of title updating depending on available space) as native back button :(
Just set a disabled back button on the navigation item of the previous view controller. Don't try to disable your custom back button if you already had one, won't work. Just set a new one which is disabled. You can reach the previous navigation item through the UINavigationBar.backItem property.
// set disabled back button
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItem.Style.plain, target: nil, action: nil)
backButton.isEnabled = false
navigationController?.navigationBar.backItem?.backBarButtonItem = backButton
// disable pop gesture
navigationController?.interactivePopGestureRecognizer?.isEnabled = false

iOS7 custom interactive transition, hidden back button reappears as "..." when cancelled

I have a custom interactive transition which requires me to hide the standard back button. Basically, the transition looks like a push from left-to-right rather than the standard right-to-left push we're all familiar with. That's why my back button is on the right side instead.
As you can see from two screenshots I took before and after cancelling pop transition activated by a UIScreenEdgePanGestureRecognizer, once the transition is cancelled there is a "..." where the back button would be.
I'm currently using
self.navigationItem.hidesBackButton = YES;
and I've tried putting it in awakeFromNib, viewDidLoad, viewDidAppear, viewWillAppear methods all without fixing the problem.
So using the power of Reveal.app I investigated the view hierarchy before and after and saw this:
What you see highlighted in each part of the image is what appears to be changing in the area of the nav bar that contains the hidden back button. Before it's a UINavigationButton and then it becomes a UINavigationButtonItem with a UILabel, which must be what contains the "..." and remains like this.
Any help would be much appreciated. I hope this is detailed enough to give a good picture of the issue.
Try creating an empty backbutton first (in the parent viewcontroller before the vc is pushed) - maybe that will prevent the "..." UILabel from being created.
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:#""
style:UIBarButtonItemStyleBordered
target:nil
action:nil];
Another idea: Just set the parent vc title to an empty string.
self.title = #"";

NSDocument based application and NSToolbar

I have application based on NSDocument (NSPersistentDocument), in application I can create (as usually) more than one document.
Main document window (based on NSPersistentDocument) has, added IB, toolbar. In code I add to toolbar item (NSToolbarItems) using methods insertItemWithItemIdentifier and - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag.
Code samples:
[_toolbar insertItemWithItemIdentifier:#"addTape" atIndex:2];
and
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
NSToolbarItem *item =nil;
if ([itemIdentifier isEqual:#"addTape"]) {
item = [[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier];
item.label = NSLocalizedString(#"Add Tape",#"Add Tape");
item.paletteLabel = NSLocalizedString(#"Add Tape",#"Add Tape");
item.toolTip = NSLocalizedString(#"Adds new tape",#"Adds new tape");
item.image = [NSImage imageNamed:#"NSAddTemplate"];
item.target = self;
item.action = #selector(addTape:);
item.tag = 101;
}
}
Everything is correct until I have opened only one document. When I open second document (or create new document) on first document window toolbar items are doubled (after opening third document, items are tripled on first window and doubled on second, and so on).
Edit: I noticed, that itemForItemIdentifier is called on each window, everytime I try to add toolbar item. In example: if I have two windows (two opened document) and on one I try to add one button itemForItemIdentifier is called two times.
It is strange to me, because every document has own toolbar with delegate set only to this document.
I don't have any idea what I have done wrong. Maybe someone will point me where I made a mistake.
You don't typically insert toolbar items yourself; implement the delegate methods toolbarAllowedItemIdentifiers: and toolbarDefaultItemIdentifiers: and the toolbar will be initialized according to those lists.
I found solution: I cannot use tooolbar created from nib, because each created this method toolbar has this same identifier. When I created toolbars in code, using different identifiers, the problem has gone.

How to make a print dialog with preview for printing an image file

I have a mac cocoa image editing application. I would like to add print image functionality to my application. I basically always have a jpg/png file with me. Whenever the user goes to File -> Print menu I would like to give user a dialog with print options/settings to print this jpg/png file. I would like the print dialog to be customized for image printing such as one we get when printing an image from Preview application.
I don't want to use something like the following because this will give a plain not very customizable print dialog:
[NSPrintOperation printOperationWithView:viewToPrint printInfo:[self.document printInfo]]
Well, you can put everything inside a NSView and then use the print method. This method will print everything that's inside the view (including subviews). Now for the customizable printing you can make something like: User clicks a button labeled "print", it makes your custom made dialog appear where the user can choose options such as, show exemple date (which is in a subview, of the view that's going to be printed), you store those options and them when the user clicks the print at your dialog, you can remove the subview he didn't wanted to show. And after its printed, show it again. There's also other methods for printing views here: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html
Please use this code.
NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
NSImage *pic = [[NSImage alloc] initWithContentsOfFile: #"/Users/Anne/Desktop/Sample.png"];
NSRect picRect = NSRectFromCGRect(CGRectMake(0, 0, pic.size.width, pic.size.height));
NSImageView *imageView = [[NSImageView alloc] initWithFrame:picRect];
[imageView setImage:pic];
NSPrintOperation * picPrint = [NSPrintOperation printOperationWithView:imageView printInfo:printInfo];
[picPrint setCanSpawnSeparateThread:YES];
[picPrint runOperation];

Problem with UISPlitViewController toolbar

I'm trying to use a toolbar in a splitviewcontroller. For some reasons that are unknown to me, the table view on the left is not resized correctly.
If I turn to portrait and open the table view from the toolbar item and then go back to landscape view, the tableview is then displayed properly. I'm not sure why this happens.
This is what I have in the RootViewController:
self.navigationController.toolbar.items = [NSArray arrayWithObjects:... nil]; // Setting these to an empty array doesn't change anything
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.barStyle = UIBarStyleDefault;
I doubt the bug is there, but the complete source code is available on github if there's something obvious to check.
I moved the code into viewDidAppear and it now works as expected.