NSView is one of Cocoa’s most complicated classes. If you understand how it works, you can control the display of information on the computer’s screen and have it updated quickly and efficiently.
Each Cocoa NSView has its own coordinate system that can be rotated, scaled, or otherwise transformed from the coordinate system of its superview.
Each NSView also has the following two methods that describe its position in its window:
Returns the NSView’s frame in the coordinate system of its superview
Returns the NSView’s frame (i.e., bounds) in its own coordinate system
When you change an NSView’s coordinate system, its
bounds
instance variable is automatically updated
to reflect the change, while its frame
instance
variable remains the same. The NSView class provides the following
methods for inspecting and changing an NSView’s
coordinate system:
Returns a floating-point number for the angle, in degrees, between an NSView’s coordinate system and the coordinate system of its superview.
Returns the angle of the NSView’s frame relative to its superview’s coordinate system. A value of 0 means that the NSView has not been rotated (but its coordinate system may have been).
Returns TRUE if an NSView or any of its ancestors have been rotated from the window coordinate system.
Returns TRUE if an NSView or any of its ancestors have been rotated or scaled from the window coordinate system.
Rotates an NSView’s coordinate system around the NSView’s origin (0,0). This method rotates the contents of the view but not the view itself.
Scales an NSView’s coordinate system. For example, a newUnitSize of (2,2) doubles the size of units along the respective axis.
Translates an NSView’s coordinate system so that its origin has the coordinates (aPoint.x, aPoint.y).
Rotates an NSView’s coordinate system so that angle is the angle between the NSView’s coordinate system and its frame.
You can convert a point or rectangle from one NSView’s coordinate system to or from another NSView’s coordinate system with one of these methods:
- (NSPoint)convertPoint:(NSPoint)aPoint fromView:(NSView *)aView - (NSPoint)convertPoint:(NSPoint)aPoint toView:(NSView *)aView - (NSSize)convertSize:(NSSize)aSize fromView:(NSView *)aView - (NSSize)convertSize:(NSSize)aSize toView:(NSView *)aView - (NSRect)convertRect:(NSRect)aRect fromView:(NSView *)aView - (NSRect)convertRect:(NSRect)aRect toView:(NSView *)aView
If you supply nil
as an argument to any of the
methods that take aView as an argument, the
methods will convert to or from window coordinates.
There are many, many more methods — consult the NSView documentation for further information.
You can move the position of an NSView relative to its superview’s coordinate system. This usually has the effect of changing where the NSView draws itself inside the window.
The following methods control the placement and movement of an NSView:
Moves the origin of the NSView’s frame to a precise position in its superview’s coordinate system
Rotates an NSView’s frame to an absolute position
Repositions and resizes an NSView within its superview’s coordinate system
Resizes an NSView by an absolute amount in its superview’s coordinate system
Views can be flipped, which means that the ordinal value of the y coordinate increases as it moves down the screen. Flipped coordinate systems are used for building subclasses of NSView such as the NSText object, which naturally move down from the upper-right corner. For these views, it’s easy to calculate the y coordinate by multiplying a line number by a constant.
The following NSView method deals with flipped views:
Most application frameworks available for Microsoft Windows, X Windows, and Mac OS 9 operate only with flipped coordinate systems. If you are coming from these platforms, you may think it’s easier to simply flip the coordinate systems of the views that you create, rather than flipping your thinking. Resist this temptation! Many functions and NSView methods do not work the way that you would expect them to if the NSView’s coordinates are flipped. Flipped NSViews also seem to exercise some bugs within the AppKit. If you can avoid using flipped NSViews, we recommend that you do so.
All views are arranged in a hierarchy. Each NSView has exactly one superview and can have zero to many subviews:
Searches up the hierarchy for an NSView that is in common with the receiving NSView and aView.
Finds the nearest descendant NSView of the receiver that has aTag as its tag.
Returns whether or not the receiver is a descendant of aView.
If flag is YES, this method causes the view to post a FrameChangedNotification when its frame changes. This is used with the NSScrollView to automatically update the size of the scrollbars. This notification is on by default; you should turn it off only for very special, temporary circumstances.
If oldView is a subview of the receiver, it is removed from the NSView hierarchy and replaced with newView.
Returns an NSArray containing the NSView’s subviews. Do not modify this list directly.
Returns the NSView’s superview.
Cocoa represents views by rectangular regions on the screen, but nothing forces the drawing that an NSView does to be rectangular. A drawing can be an odd shape, and it can even have holes through which you can see what’s behind it.
Each NSView specifies whether or not it completely fills its frame when it is drawn (so that you can’t see anything behind the NSView). If your NSView has holes in it or does not completely set every pixel within its frame, isOpaque should return NO. It is important to set this return value properly to reflect what your NSView does; this minimizes the amount of redrawing that needs to be done when your views are redisplayed.
These methods help you manage opaqueness:
NSView returns NO by default. If your NSView subclass completely fills its bounds when it is drawn, you should should override this method and return YES.
Returns the NSView’s nearest ancestor NSView that is
opaque. If the NSView is opaque, it will return
self
.
When the mouse is clicked in your NSView, the NSWindow object uses the hitTest: method to determine whether or not the NSView was clicked. You can override this method if parts of your NSView should not be mouse-sensitive — for example, if your NSView displays itself as a triangle.
Returns the lowest subview in the view hierarchy of NSViews that contains aPoint. The NSWindow class uses this method to determine in which NSView a mouseclick occurs. You can subclass this method to make some parts of your NSView “invisible” to the mouse.
Two methods are used in display:
Causes the NSView to redisplay itself and its subviews by locking focus on itself and calling displayRect:. You should almost never call this method yourself; call setNeedsDisplay: instead.
Redisplays the portion of the NSView and its subviews specified by the argument rect.
Most Cocoa views need to redisplay themselves when something about their internal state changes. For example, an NSTextField object needs to redisplay itself when the contents of the NSTextField change. If you write your own custom NSView, you may override these methods to improve drawing performance under certain circumstances.
The following methods are used for managing the redisplay of views:
Displays the receiving NSView and any of its subviews that need to be redisplayed.
Returns YES if the receiving view needs to be redisplayed.
Tells the NSView that it needs to be redisplayed when flag = YES. Views that need to be redisplayed are automatically sent a display message each time the NSApplication class finishes handling an event. Thus, multiple actions that might cause a view to require displays may result in a single display call’s being dispatched, which increases efficiency.
Tells an NSView that a region of itself and its subviews is no longer valid and needs to be redisplayed. This is used by the NSScrollView class. You can use it to improve drawing performance if you know that only part of a view needs to be redrawn.
Mac OS X Version 10.1 does not implement optimal redraw algorithms in the Application Kit. As a result, if you develop an application under Version 10.1, you will find that your NSView subclasses end up being displayed and redisplayed far more often than necessary. Nevertheless, you should still use the needsDisplay/setNeedsDisplay:/setNeedsDisplayInRect: architecture outlined above. When Apple addresses the bugs in the AppKit, your programs will run faster without additional modification.
When a window is resized, the NSWindow class automatically sends a resizeSubviews: method to the NSWindow’s content view. The resizeSubviews: method is then passed down through the view hierarchy, resizing or not resizing the subviews as necessary.
Normally, you control resizing with IB’s Autosizing Info dialog. But there are times that you might want to catch resize events and do something special. Here are the methods used by Cocoa’s resizing machinery:
Informs the NSView’s subviews that the NSView’s size has been changed from oldFrameSize.
Makes an NSView automatically resize its subviews when it is resized.
Controls how an NSView resizes when its superview is resized.
Control “live resizing,” in which the window’s contents visibly change as the window is resized. By informing the view when live resizing is taking place, you can have the view do a “quick-and-dirty” draw operation during live resizing, and then do an “expensive-but-clean” draw operation when the live resize is finished.
18.216.77.153