In Xcode 4, I can press Ctrl-6 to get a list of all the methods in the current file.
The problem is, if I have private methods declared at the top of my implementation file, say:
#interface Foo ()
-(void)tap:(id)sender;
#end
#implementation Foo
...
-(void)tap:(id)sender
{
...
}
then starting to type "tap" while the method list is visible will just take me to the declaration, since it comes first in the file, when what I really want is the implementation.
Is there any way to exclude these declarations from the method list or do I need to resort to separate Foo.h and Foo+Private.h headers?
Thanks!
You dont need to declare you private methods and you wont get a warning by default anymore. So one options is not to declare a prototype at all.
Otherwise as curthipster mentioned ctrl-6 is a good shortcut. I use this all the time (no mouse needed):
Press ctrl-6
Type the first few letter of the method name (or a word it contains and you dont even have to spell it spot on, the search filter is very good!)
Tap down until the method is selected.
Tap enter
Alternativly open the assistant with cmd-alt enter (to close use cmd-enter, see more shortcuts here). You can make the assistant editor look at the same file, so it has one part of view at the top and one at the bottom for example.
I don't think there's a way to exclude the method declarations from the Document Items popup.
If you get in the habit of using code folding, however, you might not rely so much on that popup to navigate your source code. There are commands for folding both methods and comment blocks, and you can fold all methods with one quick shortcut (command-option-shift-left arrow to fold, -right arrow to unfold by default, though you can of course customize the keys). See the Editor->Code Folding submenu for a complete list of related commands.
When you fold all comments and methods in a .m file, almost all you're left with is a list of methods that's makes it easy to find what you're looking for. You can then unfold just that method or all methods with another keystroke. It's a little strange to see all your code disappear when you first start using folding, but it's a very handy feature.
Usually, it's better to add a named category for the private methods:
#import "Foo.h"
#interface Foo( Private )
- ( void )tap: ( id )sender;
#end
#implementation Foo( Private )
- ( void )tap: ( id )sender
{}
#end
#implementation Foo
...
#end
Then you'll see each one. It may not answer your question, but at least you'll see your method.
One thing is also to organize your methods with mark pragmas:
#pragma mark - Private methods
May help you to navigate through the completion dialog...
Hope this helps...
Related
I have an application that manages different types of NSDocument subclasses (along with matching NSWindow subclasses).
For instance, it's possible that the app has one window of type A open, and two windows of type B.
Now, if a window of type B is active, and the user chooses "Close All" or hits cmd+option+W, all my app's windows are sent the close message.
But I only want all of the active window type's windows closed instead, i.e. only the two type B, not the type A window. How do I accomplish this?
I currently have no explicit menu entry for "Close All". Instead, macOS provides that automagically. If there perhaps a way to intercept a "closeAll" message? Can't find one, though.
AppKit will add the Close All menu item if there isn't one. Add an alternate menu item item with key equivalent cmd+option+W below the Close menu and connect it to your own action method.
You might succeed with overriding your document's canClose(withDelegate:,shouldClose:,contextInfo:) to return whether a document should be closed.
If this doesn't behave the way you want, you can create a subclass of NSDocumentController (if you don't have one already). Details on how to do that vary, but usually you have main (menu) XIB or main Storyboard, which has a "Document Controller" object: set its class to your custom class.
Then override closeAllDocuments(withDelegate:,didCloseAllSelector:,contextInfo:) and implement your custom logic.
Note that you should detect whether your app is about to quit and then really do close all you documents (unless you really want to prevent the app quit, e.g. because a document is dirty).
After some digging I figured out where the auto-generated "Close All" menu item sends its action to: To the closeAll: selector of the application target:
Thus my solution is to subclass NSApplication and implement the handler there, which then simply closes all windows that are of the same type (this assumes that I use specific subclasses for my different types of windows):
- (IBAction)closeAll:(id)sender {
Class windowClass = self.keyWindow.class;
for (NSWindow *w in self.windows) {
if (windowClass == w.class) {
[w performClose:sender];
}
}
}
Caution: If you adopt this pattern be aware that:
The closeAll: selector is not documented nor mentioned in the header files, meaning that Apple might feel free to change in a future SDK, though I find that unlikely. It will probably not break anything if that happens, but instead your custom handler won't be called any more.
The code simply tells all windows to close, ignoring the fact that one might reject to be closed, e.g. by user interaction. In that case you may want to stop the loop instead of continuing to close more windows (though I know of no easy way to accomplish that).
I do not know, and cannot find, the standard technical term for the drag-select functionality when the alt/option button is pressed over an NSTextView.
When alt is pressed, the crosshair appears and text can be selected/highlighted in columns/vertically, as in Xcode.
I would like to disable this functionality in my NSTextViews, how can I do that please?
Digging into the disassembly of AppKit quickly reveals a hook which tells NSTextView whether the ALT+drag interaction should be enabled. It's the private method called _allowsMultipleTextSelectionByMouse. Altering its behavior does the trick but it is achievable only via private API. In this case, it should be pretty safe to do so.
There are following two ways for altering the aforementioned method:
Approach 1: NSUserDefaults
The method internally accesses the NSProhibitMultipleTextSelectionByMouse of NSUserDefaults. You can control the boolean value for this key on the app level. The downsides of this approach are:
It can possibly be reenabled by the users of your app (e.g. via the defaults command line tool).
It affects all instances of NSTextView in your app even those you don't necessarily want to alter.
Approach 2: Swizzling
The approach I decided to go with is a simple swizzle of this method in my subclass of NSTextView.
internal final class MyTextView: NSTextView {
internal static func initializeClass() {
try? MyTextView.swizzle(
Selector(("_allowsMultipleTextSelectionByMouse")),
with: #selector(getter: swizzled_allowsMultipleTextSelectionByMouse)
)
}
#objc dynamic internal var swizzled_allowsMultipleTextSelectionByMouse: Bool {
return false
}
}
And somewhere in the app bootstrapping code like the main function you have to trigger the class initialization code by MyTextView.initializeClass().
The code snippet above uses my own wrapper around the swizzling API but there are surely some libraries out there to use or you can follow the advices from this article by PSPDFKit.
When I input #interface or #implemetation, there is no code completion. Others' code completion work fine. Is that function removed or it is a bug?
I've found the answer is that input interface or implemetation without #, search the list of auto completion and select "Objective-C Class Interface/Implemetation" and that is it.
If you don't see that one in the list, just page down until you find it that start with a {} icon. If you've used it once, it'll be at the first place in the auto completion list next time.
Is there a way to modify Xcode's (6.4/7.x beta whatever) code completion in such a way that neither the methods nor the properties of NSObject in a subclass of it are shown? I think, I don't use them frequently and it is pretty annoying when searching for another function whose name I can only slightly guess and then have to scroll through all the unnessecary suggestions coming from NSObject.
Thanks for your help
Not sure that its possible to adjust autocomplete only for NSObject and descendants (of course it might be the way), but there is another nice tool I'm using:
https://github.com/FuzzyAutocomplete/FuzzyAutocompletePlugin
It won't solve a problem of unnecessary suggestions you see, but
it's easier to add and remove from Xcode (comparing to manually internal Xcode files edit)
it solves a problem of "searching for another function whose name
I can only slightly guess"
I have an NSPopUpButton with a long menu of items, some of which are quite wide - wider than the button's closed width. Some of the menu item titles are like so:
"Start of a really long name not that interesting (important info)"
When the menu is closed, this displays as:
"Start of a really long name not th..."
I'd like it to display as:
"Start of a really l... (important info)"
I can't figure out how NSPopUpButton is creating that ellipsis. Is there a selector being called on NSMenuItem? Does NSPopUpButton or NSMenu handle that somehow?
Which class do I need to subclass and which selector to I need to override or implement?
Many thanks.
This mechanism is called truncation. There is an option in Interface Builder called Line Breaks which is grouped in the Control group. The setting you're probably looking for is called Truncate Middle which will start picking letters from the middle of the menu item.
Note however that this won't solve your problem entirely as the (important info) part might not be the only one remaining after "…", but rather Name of my Me…tem (important info). Furthermore you might also end up with the important info partially truncated. But I figure you're fine as long as the important info is some number or a few letters.
Maybe adding an image to the menu item might suit your needs more (some sort of badge)? Maybe there is also an option for attributed strings to force letters to not be truncated… not sure however.
Fabian gave me the clue I needed. Thanks!
[[self cell] setLineBreakMode: NSLineBreakByTruncatingMiddle]
However, if there is a way to get finer-grained control, that would be even better. Is there a way to control the truncation more precisely?