I'm doing something with cocoa which I think is a bit complicate for a beginner like me. I tried a few things, but I admit I need some theory first, because I would like to understand exactly the meaning of this concepts.
I see that every NSView and every class that subclasses it has one thing called frame, and one called bounds. They both have a size with width and height and an origin.
I have an NSView with an NSTableView inside of it.
I have the size of a row from the table view, and I would like to set the height of both NSView and NSTableView equal to rows*rowSize, in a way that the group NSView+subviews is automatically resized when an object is added or removed to and from the data source of the Table View.
I made some experiments, but I did end a bit confused about frame, bounds, sizes and so on. I don't know what I should change and how.
Can you please give me an hint about what bounds and frame basically are, and how can I achieve that magic resizing?
Thank you for your replies in advance. Best regards,
—Albé
The difference between frame and bounds is covered very nicely in the View Programming Guide (under View Geometry).
You'll also want to peruse the NSView Class Reference, where you'll find some handy notifications, such as NSViewFrameDidChangeNotification and handy methods such as setPostsFrameChangedNotifications:.
Related
I think I've read that when creating and constraining views exclusively in code it's acceptable to use [NSView -init] rather than the designated initialiser [NSView -initWithFrame:]. I assumed this was correct and began to construct my interface accordingly: all views fully constrained, but none with an explicit frame rectangle. Everything seemed to be working fine, and I guessed that under the hood cocoa did all the necessary frame-setting calculations. I then attempted to add a tracking area to one of my views; it failed, and after debugging I realized it was because my view had neither a frame nor a bounds.
Is the suggestion that [NSView -initWithFrame:] should be avoided when creating/constraining in code incorrect? Or is their a way to make cocoa generate the view's frame based on it's constraints? I've no problem adding constraints in code, but I'm keen to avoid the need to deduce all of my view's frame rectangles.
I have NSSplitView with NScrollView inside it and view-based NSOutlineView inside NSScrollView, it has e.g. one column. My outline view must be scrollable vertically only and it must consider minimal width of column content to fit it. I think they must return -(NSSize)fittingSize with values {minColumnWidth, 0}, but it returns {0,0}. How can I do that?
Try to return the desired view size in (NSSize)intrinsicContentSize. I am not sure if I totally understand your scenario. You could add a screenshot or wireframe to make it easier to understand the setup. Whatsoever, take a look at my question dealing with a similar problem.
Maybe also check out the WWDC Session 232 - Auto Layout by Example. It covers a new split view API together with Autolayout (starting around 41:00 minutes).
I've really searched for an answer to this one but not come up with anything solid so here goes.
I'm dynamically adding UILabels to a view, they could be any size.
I would like the second added one to be placed about 2 pixels below the last regardless whether there is letters that go bellow the line.
I've tried using various method the get the labels frame after it has been sized to font but with no look. The frame always seems to be bigger than the actual text vertically.
Have you guys got any ideas?
First, I'd try setting the label's adjustsFontSizeToFitWidth to NO and see if that it will allow you to mess up the normal proportions, as seems to be your goal.
If that doesn't work, you probably need to draw the string to a CALayer. Create a CALayer and add it to your view's root layer, i.e.:
[yourView.layer addSublayer.yourNewLayerForString].
Set the sublayer's delegate to the class which will do the drawing:
[yourNewLayerForString setDelegate:self];
And implement drawLayer in that class (the one you assigned as delegate). The drawLayer code can be kind of ugly, but you can find examples out there for how to draw a string in a layer. This one looks good: addTextToLayer.
You will then have exact control over the font and string size, and can adjust the layer frame and the view frame to suit your aims.
I have an NSMutableArray of jpg images and I want to be able to touch and, moving my finger from right to left, move through the array of images in order. I've been reading about UIScrollView, but I'm not sure if this accomplishes what I am looking for. It seems to me that UIScrollView is more used for viewing an object that is too large to be displayed entirely on the screen and you need to be able to move to see every part of the object. I need to move to an entirely new image, the next image in my array. What is the best way to go about this?
You certainly can use a UIScrollView for what you want. A scroll view can be used, as you noted, to scroll an area that is too large for the screen. However, you can also use it to scroll through "pages". This is really the best way to do what you want, short of rolling your won scroll view.
There is a property of UIScrollView, called pagingEnabled, which you'll want to set to YES. I suggest that you give it a try. Also, have a look at the UIScrollView documentation and the Scroll View programming guide. It will tell you all that you need to know about UIScrollViews. Also, remember that for proper memory management, you'll want to only load three images at any given time. See this answer that I wrote for more information on that, and on UIScrollViews in general.
in my program, I'm implementing a custom view, a bit like a table view. To do so, I have subclassed NSView. Now my question is, what's the most efficient way to draw all the table view cells. Should I just use NSViews or possibly something else, like CALayers?
Thanks!
P.S.: This is on Mac OS X, not on iOS.
Based on your question and comment, I propose two alternatives:
NSCollectionView / NSCollectionViewItem - This is useful only if all of your "cells" (instances of your prototype view) are the same dimensions. That is, you can't have one that's wider or taller than the others (or narrower or shorter). This is highly efficient and a ready part of AppKit. Even with a single column and n rows, it works like a charm.
Roll Your Own - This is harder but gives you flexibility. Much like NSCollectionView / NSCollectionViewItem, you'd have a view that serves as the container and you'd ideally have a view you reuse to draw the various "items" it's showing. Using the same view to set its represented object and "stamp" it into place (pose it and draw it), you can roll through your entire collection in one go then use that same view as the live, active view for whatever selected, focused item you have. Even faster: roll through and cache the images and sizes of each item with your reusable item view and draw all from the cache except the selected item (which would use a live, real view posed in its proper location, updating the cached image of itself as its contents change for when it's not selected). Faster still: 1 live view and 1 "for caching" view, and draw only the computed rects of the cached images that intersect the visible rect (sans the "live" / selected view). Note: the caching will have to be re-done each time the container's frame's width changes, since presumably shrinking horizontally means all items grow vertically. If you can, take advantage of NSOperation / NSOperationQueue to handle the caching in the background, only flagging for re-display when all cached items 0 - n (where n is the highest-indexed item intersecting the visible rect) are available.
I use something very close to the latter in one of my own applications, where the "item" is an entry with varying-length text. I don't employ all the tactics I mentioned in my own solution but most and the performance increase is very satisfying. :-)
Hope this helps.