how to reference NSTableView inside NSView Class (Cocoa)? - macos

I m trying to implement a mac application, basically I have a NSTableView inside a NSView.
I implemented a drag & drop of multiple files feature on the NSView, now I want to update NSTableView with the files names just dropped.
So I need to reference NSTableView in my NSView and try reloadData to reload tableview.
I have tried initialised tableview controller in NSView and it seems not working?
MyTableController *testController = [[MyTableController alloc] init];
testController.nsMutaryOfDataObject = [[NSMutableArray alloc]init];
int i;
for (i = 0; i < 20; i ++) {
NSString * zStr1 = [[NSString alloc]initWithFormat:#"%d",(i + 1) * 10];
NSString * zStr2 = [[NSString alloc]initWithFormat:#"%d",((i + 1) * 100) + 2];
NSString * zStr3 = [[NSString alloc]initWithFormat:#"%d",((i + 1) * 1000) + 3];
MyDataObject * zDataObject = [[MyDataObject alloc]initWithString1:zStr1
andString2:zStr2
andString3:zStr3];
[testController.nsMutaryOfDataObject addObject:zDataObject];
} // end for
[testController.idTableView setHeaderView:nil];
[testController.idTableView reloadData];
Xib file as below:
Anyone can help me out?

A tableview has TWO different aspects: the view (presentation of data; drag and drop) and the datasource (an array combined with an array controller).
Usually a tableview leads a life on its own, independent from the view it is positioned in. So concentrate yourself first on the datasource-aspect and second on the drag-and-drop-aspect.
"TableView reload" simply means load the assigned array again.
For the data structure in your array a model is strongly recommended.
The names of the different parts in your model are bound to the columns in your table.
The array is the datasource to your tableview.
Use an array controller.
Your fileNames must be in the array, organized in the manner of the model...
Because a tableview is always part (subview) of an NSScrollView, assure that your really have selected the tableview itself.
In the documentation are fairly good samples for working with tableviews, with and without bindings, also "TableViewLinks" handling URLs...
Your code is missing the basic methods for a tableview to work, so start from scratch with a sample.

Sounds, as if the TV is working correctly
and
you have the fileNames available in the NSView class
and
don't want to implement the drag and drop functionality also in the class for the TV.
Then you could use a notification that is sent from the NSView-class to the TV-class with the fileNames-data attached. After receiving in the tv-class the fileNames could be used/added to the array. I once have created such a solution, it works perfect.
It also assures encapsulation of the classes.

Related

Unable to get tab order working within NSPopover

I have a View within an NSPopover, and I am unable to set the tab order correctly. I have set the nextKeyView within my 4 text fields. But it tends to flip from TextField1 to Search1, instead of TextField1 -> TextField2. I have tried inserting [self.view.window makeFirstResponder:textField1] also [self.view.window setInitialFirstResponder:textField1] along with recalculatekeyviewloop but with no luck.
Any help would be much appreciated.
I had a similiar problem when composing the popover-view of certain subviews programatically in awakeFromNIB. I could solve the problem by inserting the subviews after the popover had its private NSPopoverWindow set (i.e. it was shown the first time). It seems like the popover is re-evaluating the view-loop when the popover-view is embedded in the private child-window - ignoring the view-loop given in the view.
You could try the following:
-(void) popoverDidShow:(NSNotification *)notification{ // NSPopoverDelegate-method
if (!popoverDidShowForTheFirstTime){
[self setUpViews];
}...
-(void) setUpViews{
popoverDidShowForTheFirstTime = YES;
// insert views and establish nextKeyViews ...

Can't get subview animation to appear even after alloc :)

I have a subview loaded into an UIView. In the subview's .m file I have the following:
- (void)startAnimation {
// Array to hold png images
imageArray = [[NSMutableArray alloc] initWithCapacity:22];
animatedImages = [[UIImageView alloc] initWithImage:viewForImage];
// Build array of images, cycling through image names
for (int i = 1; i < 22; i++){
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"image%d.png", i]]];
}
animatedImages.animationImages = [NSArray arrayWithArray:imageArray];
// One cycle through all the images takes 1 seconds
animatedImages.animationDuration = 2.0;
// Repeat forever
animatedImages.animationRepeatCount = 0;
// Add subview and make window visible
[viewForMovie addSubview:animatedImages];
// Start it up
animatedImages.startAnimating;
NSLog(#"Executed");
}
Please be noted that I have in the .h file:
UIImageView *animatedImages;
NSMutableArray *imageArray;
UIView *viewForMovie;
#property(nonatomic,retain)IBOutlet UIView *viewForMovie;
and in the .m file:
#synthesize viewForMovie;
and I have connected viewForMovie to a UIView in IB. I've been on this for several hours now and have tried many variations I've found on the web but cannot get it to work. There are no errors and the other GUI graphics in the subview appear very nicely....but the animation just doesn't appear over top where it should. Also the NSlog reports that the method has in fact been called from the parent. Can anyone see any blaring issues? Thx.
PS: I'm pretty new at this.
Based on the code shown and the behavior you see so far, here are my suggestions:
Make sure the viewForMovie IBOutlet is connected properly in Interface Builder. If it's not connected properly (and so nil), nothing will appear. If you didn't mean to make it an IBOutlet in the first place, then you'll need to manually create it and add it as a subview to self before using it.
Not sure why you have the viewForMovie UIView in the first place. Is this subview's class (let's call it MySubview) a subclass of UIView? You can just show the animation in self instead of adding another subview inside it. Are you going to add more uiviews to this subview besides the viewForMovie?
To get rid of the "may not respond to" warning, declare the startAnimation method in the MySubview.h file (under the #property line):
-(void)startAnimation;
The fact that the warning says "UIView may not respond" also tells you that the parent view has declared newView as a UIView instead of MySubview (or whatever you've named the subview class). Change the declaration in the parent from UIView *newView; to MySubview *newView;.
In the initWithImage, what is "viewForImage"? Is it a UIImage variable or something else?
If all of the images are the same size and fit in the subview as-is, you don't need to set the frame--the initWithImage will automatically size the UIImageView using the init-image dimensions.
Double check that the images you are referencing in the for-loop are named exactly as they are in the code and that they have actually been added to the project.
Finally, you should release the objects you alloc in startAnimation. At the end of the method, add:
[imageArray release];
[animatedImages release];
The only item, however, that I think is actually preventing the animation from appearing right now is item 1.

How to handle unknown UILabel height and its effect on labels underneath in Interface Builder?

I have two UILabels in a XIB file, one on top of the other, the contents of which are loaded from a JSON source file on the net.
Given that I'm unsure of the number of lines the labels will take up, and hence the height, how best should I position these relative to each other.
I know in some Java GUI frameworks, one can use various container elements, and in HTML this flow of layout would be the default, but I can't find anything that would seem to do the trick.
Can I do this in Interface Builder, or does this have to be done programmatically?
Thanks for your help..
Edit:
I now have the answer, although it may not be perfect. I have two labels, titleLabel above descLabel. This is how I achieved it:
titleLabel.text = [data objectForKey:#"title"];
descLabel.text = [data objectForKey:#"description"];
CGSize s;
s.width = descLabel.frame.size.width;
s.height = 10000;
titleLabel.frame = CGRectMake(titleLabel.frame.origin.x,
titleLabel.frame.origin.y,
titleLabel.frame.size.width,
[[data objectForKey:#"title"] sizeWithFont:titleLabel.font constrainedToSize: s lineBreakMode:titleLabel.lineBreakMode].height
);
descLabel.frame = CGRectMake(descLabel.frame.origin.x,
titleLabel.frame.origin.y + [[data objectForKey:#"title"] sizeWithFont:titleLabel.font constrainedToSize: s lineBreakMode:titleLabel.lineBreakMode].height + 10,
descLabel.frame.size.width,
[[data objectForKey:#"description"] sizeWithFont:descLabel.font constrainedToSize: s lineBreakMode:descLabel.lineBreakMode].height
);
weffew
You’ll have to do this programatically. The NSString method -sizeWithFont:constrainedToSize:lineBreakMode: (which is actually in a UIKit category) will be of particular use for this.

Dynamic Results and Covering Data

Today I have a question that sprouted off of this one: Database Results in Cocoa. It's regarding using the data that was returned by a database to create a certain number of questions. I am using a form of the following code (this was posted in the question).
NSMutableDictionary * interfaceElements = [[NSMutableDictionary alloc] init];
for (NSInteger i = 0; i < numberOfTextFields; ++i) {
//this is just to make a frame that's indented 10px
//and has 10px between it and the previous NSTextField (or window edge)
NSRect frame = NSMakeRect(10, (i*22 + (i+1)*10), 100, 22);
NSTextField * newField = [[NSTextField alloc] initWithFrame:frame];
//configure newField appropriately
[[myWindow contentView] addSubview:newField];
[interfaceElements setObject:newField forKey:#"someUniqueIdentifier"];
[newField release];
}
However, now when I attempt to use IFVerticallyExpandingTextfield (from http://www.cocoadev.com/index.pl?IFVerticallyExpandingTextField), or create any large amount of text, it simply goes over the other drawn content. I looked into using setAutosizingMask: on the object, but it has not worked so far.
Thanks for any help.
EDIT: What I want the effect to look like is called "Correct TextField" and what happens is called "StackOverflow Sample" - http://www.mediafire.com/?sharekey=bd476ea483deded875a4fc82078ae6c8e04e75f6e8ebb871.
EDIT 2: And if no one knows how to use this IFVerticallyExpandingTextfield class, would anyone know if there is another way to accomplish the effect?
Do you mean this?
http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/GraphicsContexts/GraphicsContexts.html
Your question is not very clear to me but this might help ^^^.
Look at 'Modifying the Current Graphics State' on that page.
What about just exactly copying the code from the 'Correct textfield' example and use it in your application? Or start your application from the 'Correct texfield' example.
Also
A comment on http://www.cocoadev.com/index.pl?IFVerticallyExpandingTextField says:
Give it a try! You should be able to
throw this into a project, read the
files in Interface Builder, and use
the custom class pane to make an
NSTextField into an
IFVerticallyExpandingTextField. You'll
need to set the layout and
linebreaking attributes for word
wrapping for this to work.
Although expansion should work
properly when the textfield is
embedded in a subview, I'm having some
trouble dealing with NSScrollViews.
The field expands into the
scrollview's content view, but none of
the controls on the scrollbar appear.
Some help here would be appreciated.

How can I detect that the number of rows in an NSTableView has changed?

I have a custom NSTableView subclass which is bound to a data source (an NSArray) which updates asynchronously. When items are added to the array, rows are automatically added to the tableview. Awesome!
My question is this: How can I detect that this magic has happened so that I can perform some other tasks related to the display of my custom tableview? Is there a method that I can override in my subclass which will be called when the tableview is updated?
You don't need to subclass NSTableView to change its height based on the number of rows. In your controller, just monitor the data array using KVO and adjust the frame size of the tableview's scrollview (you can find it using enclosingScrollView) when rows are added or removed. I've used this technique before and it's worked well. You can use the tableview's rowHeight and intercellSpacing methods to calculate the height of the frame.
Looked high and low for days on this solution. It worked like a charm, thanks! Here's a sample of my code for others to follow:
// tv = NSTableView
// view = NSView
int height = ([tv rowHeight] + [tv intercellSpacing].height) * [itemNodes count];
NSScrollView *sv = [tv enclosingScrollView];
NSRect svFrame = [sv frame];
svFrame.size.height = height;
[sv setFrame:svFrame];
NSRect viewFrame = [view frame];
viewFrame.size.height = height;
[view setFrame:viewFrame];

Resources