In XCode 6, using Swift; lets say I'm creating an instance of some object:
let sessionConfiguration = NSURLSessionConfiguration()
Is there a way to tell XCode 6 code completion to only include methods/properties that is actually defined on the NSURLSessionConfiguration class or it's super classes?
Using the object defined above XCode code completion suggests that I use methods like:
sessionConfiguration.accessibilityActionDescription(action: String)
sessionConfiguration.animationDidStart(anim: CAAnimation!)
But I can't see that those methods would be relevant for this class.
This seems like odd behavior in the new Swift programming paradigm obsessed with code safety.
extension NSObject {
/* Called when the animation begins its active duration. */
func animationDidStart(anim: CAAnimation!)
/* Called when the animation either completes its active duration or
* is removed from the object it is attached to (i.e. the layer). 'flag'
* is true if the animation reached the end of its active duration
* without being removed. */
func animationDidStop(anim: CAAnimation!, finished flag: Bool)
}
extension NSObject {
/*
Implement accessibilityActivate on an element in order to handle the default action.
For example, if a native control requires a swipe gesture, you may implement this method so that a
VoiceOver user will perform a double-tap to activate the item.
If your implementation successfully handles activate, return YES, otherwise return NO.
default == NO
*/
#availability(iOS, introduced=7.0)
func accessibilityActivate() -> Bool
...}
The two methods are Extension of NSObject declare in CAAnimation and UIAccessibility
Based on bumaociyuan's answer. The answer to my original question is:
No.
XCode autocompletion shows every method in the class hierarchy. Some methods are added to the class through inheritance, some by extensions.
Related
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.
This is bizarre. I have a simple storyboard placeholder with GridView for the class name attribute.
class GridView: NSView {
required init?(coder: NSCoder) {
super.init(coder: coder)
print("coder: \(coder)")
}
override func drawRect(dirtyRect: NSRect) {
let rect = NSBezierPath(rect: dirtyRect)
NSColor.redColor().setFill()
rect.fill()
}
}
This worked as expected with just drawRect implemented, but after I added the initialiser it started opening the print dialog every time I run the app.
Why does this happen and how can I properly reimplement the storyboard initialiser for a custom view?
Calling print() does something different as it should - more precisely: something different as you would expect. It calls NSView's print(sender: AnyObject?) instead of the logging print. You could consider this as a bug or at least as quite unexpected behavior since the Swift.print(...) is generally much more used.
This action method opens the Print panel, and if the user chooses an option other than canceling, prints the receiver and all its subviews to the device specified in the Print panel.
Take a look at this post in the apple dev forum.
In fact it is not a bug since calling the print which is "closer" in the current context is certainly the correct way. Calling the parent's print is a lot more reasonable than calling some arbitrary other print. Only the fact that you normally use the other print is the confusing point here since in general you do not worry in what scope the logging print is located - it just works. If you think the other way around and would want to use the printing print of your parent it would be a lot more confusing having to explicitly state that you want to use the parents print and not the Swift.print(...).
The only "solution" would be to use different names for the two functions which is probably not going to happen.
The reason it's calling the print dialog is that Swift 2 apparently has two methods with the same signature.
This is a pretty old thread, but I must add here that you can write:
Swift.print("something")
and you would be using the "log print" function instead of view's one.
I have a custom view controller that loads objects from a XIB, one of which is an NSPopover.
I have a method on the view controller that essentially passes through to the popover, like so:
func showRelativeToRect(positioningRect: NSRect, ofView positioningView: NSView!, preferredEdge: NSRectEdge) {
self.popover.showRelativeToRect(positioningRect, ofView: positioningView, preferredEdge: preferredEdge)
}
However, this causes a compilation error that I don't quite understand:
/Users/Craig/projects/.../EditItemPopoverController.swift:23:102: 'NSRectEdge' is ambiguous for type lookup in this context
This seems to be caused by the conflicting available types of NSRectEdge, which is substantiated by the autocomplete:
How can I tell Swift that I would like to use a particular type? Diving into the NSPopover.swift class, it seems it is using the version:
typealias NSRectEdge = Int
But I don't know how to tell the Swift compiler, in my view controller, that this is the type I want to use. I'm able to workaround this issue by defining my method to take Int instead of NSRectEdge, but I'd like to use the same method signature as the popover.
I tried compiling a test project with this code with:
typealias NSRectEdge = Int
at the top of the file, and it worked - perhaps just redeclaring it works. This isn't documented anywhere though.
Really I think there should be a separate command such as using in c#, but that's not there yet.
This appears to be resolved in the most recent beta. (Or maybe Beta 6. All I know is that it works properly in Beta 7.)
While setting up an NSAlert object to be displayed as a modal sheet in Xcode 5.0.2, I hit an interesting surprise.
I was planning on using beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:
As I started to enter it, Xcode autofilled beginSheetModalForWindow:completionHandler: for me (even though I cannot find this in any NSAlert documentation).
I prefer to use completion handlers rather than delegate/selector as a callback mechanism, so I went ahead and tried it. I was pleasantly surprised to find that it worked perfectly.
Three quick questions before I commit to this.
Am I missing something in the documentation?
Is it "safe" to use this feature if it is undocumented? (i.e. will it magically disappear as mysteriously as it appeared?)
I'd rather not hardcode the response values based on what I'm seeing via logging. Does anybody know the "proper" NS...Button constants?
This call is “safe” but it’s 10.9+ only. Here it is from the header file:
#if NS_BLOCKS_AVAILABLE
- (void)beginSheetModalForWindow:(NSWindow *)sheetWindow completionHandler:(void (^)(NSModalResponse returnCode))handler NS_AVAILABLE_MAC(10_9);
#endif
It appears they just accidentally left it out of the current docs. The headers are generally considered the “truth” in Cocoa, though—they authoritatively tell you what’s deprecated and what’s new. (Unlike in X11, for instance, where the documentation was declared to be correct over the actual implementations or the headers.)
These are the constants you want to use inside your completionHandler block:
/* These are additional NSModalResponse values used by NSAlert's -runModal and -beginSheetModalForWindow:completionHandler:.
By default, NSAlert return values are position dependent, with this mapping:
first (rightmost) button = NSAlertFirstButtonReturn
second button = NSAlertSecondButtonReturn
third button = NSAlertThirdButtonReturn
buttonPosition 3+x = NSAlertThirdButtonReturn + x
Note that these return values do not apply to an NSAlert created via +alertWithMessageText:defaultButton:alternateButton:otherButton:informativeTextWithFormat:, which instead uses the same return values as NSRunAlertPanel. See NSAlertDefaultReturn, etc. in NSPanel.h
*/
enum {
NSAlertFirstButtonReturn = 1000,
NSAlertSecondButtonReturn = 1001,
NSAlertThirdButtonReturn = 1002
};
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...