I wrote a method to add new rows to NSTableView. It adds new rows, but there're empty, without text.
Here's code:
AppDelegate.h
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
IBOutlet NSButton *addDreamButton;
IBOutlet NSButton *removeDreamButton;
IBOutlet NSTextField *dreamField;
IBOutlet NSTableView *dreamTable;
IBOutlet NSMutableArray *dreamlist;
IBOutlet NSTextField *testf;
}
- (IBAction)addDream:(id)sender;
- (IBAction)deleteDream:(id)sender;
#property (assign) IBOutlet NSWindow *window;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window = _window;
-(int) numberOfRowsInTableView: (NSTableView *) tableView
{
return [dreamlist count];
}
-(void) dreamTable: (NSTableView *) tableview
setObjectValue:(id)anObject
objectValueForTableColumn: (NSTableColumn *) tablecolumn
row:(int) rowIndex
{
[dreamlist replaceObjectAtIndex:rowIndex withObject:anObject];
}
- (IBAction)addDream:(id)sender
{
NSString* thedream = dreamField.stringValue;
[dreamlist addObject: thedream];
[dreamTable reloadData];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
dreamlist = [[NSMutableArray alloc] init];
}
#end
AppDelegate is bound as datasource with TableView.
So when I press "add" button empty rows appears in table (textfield where I get text is not empty; I debugged and saw that MutableArray contains right strings).
Your table view data source needs to implement this method:
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
return [dreamlist objectAtIndex:rowIndex];
}
Related
I have an OS X application with a main view (i.e., self.view) that contains an NSScrollView and the NSScrollView contains a custom NSView. The custom NSView (flippedNSView) is just an NSView custom class FlippedNSView with a -(BOOL)isFlipped { return YES; }
I have a function that creates a NSButton that is called in the ViewDidLoad.
If button is added to self.view, button works fine
If button is added to flippedNSView, button does not respond.
NSTextViews work fine and respond to MouseDown events, although they do not respond to text selection. Only the buttons do not respond.
Any ideas?
AppDelegate.h
#import "CodeObjViewController.h"
#interface AppDelegate : NSObject <NSApplicationDelegate> {
FlippedView *flippedNSView;
}
// Windows are defined in MainMenu.xib with the following hierarchy
// Window
// |_ View
// |_ flippedNSView
// |_ scrollView
// |_ myCustomView
#property (assign) IBOutlet NSWindow *window;
#property (strong) IBOutlet NSViewController *myViewController;
#property (weak) IBOutlet NSView *myCustomView;
#property(readwrite, strong, nonatomic) IBOutlet NSScrollView* scrollView;
#property(readwrite, strong, nonatomic) IBOutlet FlippedView * flippedNSView;
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
#synthesize scrollView;
#synthesize flippedNSView;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
_myViewController = [[CodeObjViewController alloc] initWithNibName:#"customViewController" bundle:nil];
[_myCustomView addSubview:[_myViewController view]];
[[_myViewController view] setFrame:[_myCustomView bounds]];
[scrollView setDocumentView: flippedNSView];
}
customViewController.h
#interface FlippedView : NSView
#end
//----------------------------------------------------------
#interface CodeObjViewController : NSViewController {
FlippedView *flippedNSView;
NSScrollView *scrollView;
}
customViewController.m
#implementation FlippedView
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
return self;
}
//----------------------------------------------------------
- (BOOL)isFlipped {
return YES;
}
#end
//----------------------------------------------------------
#implementation customViewController
// Custom View Controller
-(void) viewDidLoad {
// The scroll and flipped views are defined on menu.xib and declared on the AppDelegate.
AppDelegate *theAppDelegate = (AppDelegate*) [NSApplication sharedApplication].delegate;
flippedNSView = theAppDelegate.flippedNSView;
scrollView = theAppDelegate.scrollView;
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(0,0,10,10)];
[self.view addSubview:helpButton]; // THIS RESPONDS TO MOUSE DOWN
[flippedNSView addSubview:helpButton]; // THIS DOES NOT RESPOND TO MOUSE DOWN
[button setAction:#selector(buttonClicked:)];
[button setTarget:self];
}
-(void) buttonClicked : (id) sender {
NSLog(#"Button clicked");
}
I want to present a UItableViewController when a button is press using popoverPresentationController.
It works ok if the device is not rotated, but if the device is rotated the preferredContentSize it is not ok.
The code:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
#import "ViewController.h"
#import "TableViewController.h"
#interface ViewController () <UIAdaptivePresentationControllerDelegate>
#end
#implementation ViewController
- (IBAction)showActionButtonPress:(id)sender {
TableViewController *tableViewController = [[self storyboard] instantiateViewControllerWithIdentifier:#"TableViewController"];
tableViewController.modalPresentationStyle = UIModalPresentationPopover;
tableViewController.popoverPresentationController.sourceView = sender;
tableViewController.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown;
UIPresentationController *presentationController = tableViewController.presentationController;
presentationController.delegate = self;
tableViewController.preferredContentSize = CGSizeMake(414.0, 174.0);
[self presentViewController:tableViewController animated:YES completion:nil];
}
#pragma mark - <UIAdaptivePresentationControllerDelegate>
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller{
NSLog(#"%#: %#", NSStringFromSelector(_cmd), self);
return UIModalPresentationNone;
}
#end
#import <UIKit/UIKit.h>
#interface TableViewController : UITableViewController
#end
#import "TableViewController.h"
#import "TableViewCell.h"
#implementation TableViewController
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
// return 210;
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//return UITableViewAutomaticDimension;
return 174.0;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"%#: %#", NSStringFromSelector(_cmd), self);
NSString *CellIdentifier = #"CellIdentifier";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.imageView.image = [UIImage imageNamed:#"ball.png"];
cell.label1.text = #"One";
cell.label2.text = #"Two";
cell.label3.text = #"Three";
cell.label4.text = #"Four";
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
#end
#import <UIKit/UIKit.h>
#interface TableViewCell : UITableViewCell
#property (nonatomic, strong) IBOutlet UIImageView *cellImageView;
#property (nonatomic, strong) IBOutlet UILabel *label1;
#property (nonatomic, strong) IBOutlet UILabel *label2;
#property (nonatomic, strong) IBOutlet UILabel *label3;
#property (nonatomic, strong) IBOutlet UILabel *label4;
#end
#import "TableViewCell.h"
#implementation TableViewCell
#end
Image Portrait:
Image LandScape:
I have implemented a application in which I use NSTableview with the help of its data source and delegates I have not used NSArrayController nor I want to use it. My question is how can I bind NSSearchField with my NSTableView in this situation? I had seen a lot of answer using NSArrayController.
I do not want to convert implementation to NSArrayController as things are working good with NSMutableArray.
TableView is a display control and is not for filtering.
You should add 2 NSArray properties;
1) #property(nonatomic, strong) NSArray *allItems;
2) #property(nonatomic, strong) NSArray *filteredItems;
#import "ViewController.h"
#interface ViewController()<NSSearchFieldDelegate, NSTableViewDelegate, NSTableViewDataSource>
// Your NSSearchField
#property (weak) IBOutlet NSSearchField *searchField;
// Your NSTableView
#property (weak) IBOutlet NSTableView *tableView;
// In this array you will store all items
#property(nonatomic, strong) NSArray *allItems;
// In this array you will store only filtered items
#property(nonatomic, strong) NSArray *filteredItems;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.searchField.delegate = self;// You can set delegate from XIB/Storyboard
self.tableView.delegate = self;// You can set delegate from XIB/Storyboard
self.tableView.dataSource = self;// You can set dataSource from XIB/Storyboard
self.allItems = #[#"Test1", #"Demo filter", #"Test 2", #"Abracadabra"];
[self applyFilterWithString:#""];
}
- (void)controlTextDidChange:(NSNotification *)obj{
if (obj.object == self.searchField) {
[self applyFilterWithString:self.searchField.stringValue];
}
}
-(void)applyFilterWithString:(NSString*)filter {
if (filter.length>0) {
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:#"self CONTAINS[cd] %#", filter];
self.filteredItems = [self.allItems filteredArrayUsingPredicate:filterPredicate];
}
else {
self.filteredItems = self.allItems.copy;
}
[self.tableView reloadData];
}
#pragma mark - ***** NSTableViewDataSource, NSTableViewDelegate *****
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return self.filteredItems.count;
}
// for the "Cell Based" TableView
- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row {
NSString *item = self.filteredItems[row];
return item;
}
#end
I am using XCode 6 on OS X 10.10 and have a storyboard containing a window with a split view controller, as shown in the following image.
The split view controller (highlighted in the image) is an instance of MyViewController, which has the following code:
MyViewController.h
#import <Cocoa/Cocoa.h>
#interface MyViewController : NSSplitViewController <NSTableViewDataSource>
#end
MyViewController.m
#import "MyViewController.h"
#implementation MyViewController
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return 7;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return [NSString stringWithFormat:#"%ld", (long)row];
}
#end
I would like to make the view controller the dataSource of the NSTableView in my storyboard, however I am unable to connect them. Is there a reason for this?
In your NSSplitViewController-subclass viewDidLoad-method set the data source programmatically. You need to implement the child view controller class as well (with the tableView outlet connected to the control).
MySplitViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
for (NSSplitViewItem *item in self.splitViewItems)
{
NSViewController *controller = item.viewController;
if ([controller isKindOfClass:[MyChildController class]])
{
MyChildController *myController = (MyChildController *)controller;
myController.tableView.dataSource = self;
[myController.tableView reloadData];
}
}
}
But to tell you the truth I don't like this approach. It's more better when the table view's data source methods are in the native view controller class.
Another way to do that. MyChildController.h file:
#class MyChildViewController;
#protocol MyChildControllerDelegate <NSObject>
- (void)childController:(MyChildViewController *)controller didSelectRowAtIndex:(NSUInteger)index;
#end
#interface MyChildViewController : NSViewController <NSTableViewDataSource, NSTableViewDelegate>
#property (nonatomic, weak) id<MyChildControllerDelegate> delegate;
#property (nonatomic, retain) NSArray *items;
#property (nonatomic, weak) IBOutlet NSTableView *tableView;
#end
Don't forget to implement all the table view dataSource and delegate methods you need. MySplitViewController.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
for (NSSplitViewItem *item in self.splitViewItems)
{
NSViewController *controller = item.viewController;
if ([controller isKindOfClass:[MyChildController class]])
{
MyChildController *myController = (MyChildController *)controller;
myController.delegate = self;
[myController setItems:_items];
}
}
}
Logic is: read data from a view (3 textfields) then when a button is pressed, sum data which stored in the model and print it out.
<--Header file-->
#import <Cocoa/Cocoa.h>
#class QuoteAttributes;
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
#property (weak) IBOutlet NSTextField *amountOfHardware;
#property (weak) IBOutlet NSTextField *amountOfPrinter;
#property (weak) IBOutlet NSTextField *amountOfSoftware;
#property (strong) QuoteAttributes *quickQuote;
- (IBAction)calculate:(id)sender;
- (void) setValueTotheForm;
#end
See the following Code:
#import "AppDelegate.h"
#import "QuoteAttributes.h"
#implementation AppDelegate
#synthesize amountOfHardware;
#synthesize amountOfPrinter;
#synthesize amountOfSoftware;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
- (void) setValueTotheForm{
[self.quickQuote setNumHardware:[self.amountOfSoftware intValue]];
[self.quickQuote setNumPrinter:[self.amountOfPrinter intValue]];
[self.quickQuote setNumSoftware:[self.amountOfSoftware intValue]];
int totalQuote = [self.quickQuote numHardware] + [self.quickQuote numPrinter] + [self.quickQuote numSoftware];
NSLog(#"%d", totalQuote);
}
- (IBAction)calculate:(id)sender {
[self setValueTotheForm];
}
#end
However, when I call this method, it prints 0
should initiate the object first :
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
QuoteAttributes *qa = [[QuoteAttributes alloc] init];
[self setQuickQuote: qa];
}
then the abovementioned code will work.