I have the following code to support dropping an app file into a table view. The problem is that I don't even see the green + when I drag and drop. I think it has something to do with the registerForDraggedTypes: but I'm not sure. I've tried many tutorials and none have worked for me.
- (void)awakeFromNib {
[apps registerForDraggedTypes:[NSArray arrayWithObject:#"app"]];
}
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
{
return YES;
}
- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
{
return NSDragOperationCopy;
}
- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info
row:(int)row dropOperation:(NSTableViewDropOperation)operation
{
return YES;
}
Thanks in advance
registerForDraggedTypes isn't looking for an array of file extensions; it takes an array of uniform type identifiers. If you want to accept filenames, use the NSFilenamesPboardType:
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
Then, to only accept .app files, check the extension and return YES from tableView:acceptDrop:row:dropOperation:, getting the appropriate information from the NSDraggingInfo and its pasteboard.
Related
Helo!
I feel really silly asking for help, but oh well I got stuck with my first Xcode project.
So I am creating a calculator and I have created a method that prints out two results to two STrings
-(IBAction)calculate:(id)sender {
(...)
stringResult=[[NSString alloc]
initWithFormat:#"%1.2d",intResult];
stringTimeResult=[[NSString alloc]
initWithFormat:#"%1.2d",intTimeResult];
[stringTimeResult release];
[stringResult release];
}
And I have prepared Segue transfer two Strings to Two Labels on a new view, creating a form or result to a given calculations.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSLog(#"prepareForSegue: %#", segue.identifier);
if([segue.identifier isEqualToString:#"Answer"])
{
[segue.destinationViewController setTransferStr:stringTimeResult];
[segue.destinationViewController setTransferStr2:stringResult];
}
And a view did load in new controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.TimeResult.text = self.transferStr;
self.Result.text = self.transferStr2;
}
However, im experiencing a lot of trouble! Forgive me my lack of knowledge but i just can't figure it out!
The main bit is that the answer of the calculation is displayed on two labels on a next view controller!
Thank you for your help in advance
Grace
there are 2 view controllers "vcA" and "vcB", connected by segue called"AtoBSegue"
now you have some data want to transfer from vcA -> AtoBSegue -> vcB:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"AtoBSegue"]){
vcB *viewcontrollerB = (vcB*)segue.destinationViewController;
viewcontrollerB.labelAtvcB = self.labelAtvcA.text; //labelAtvcB is the label from vcB, labelAtvcA is the label from vcA.
}
}
Note: please define the exact name as you use labelAtvcB in vcB (destination view controller)
I'm trying to have a custom subclass of NSTableView observe the value of its own -selectedRowIndexes property, and I'm having trouble figuring out how to receive the notifications properly. My subclass looks like this (using ARC):
#implementation MyTableView
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self addObserver:self forKeyPath:#"selectedRowIndexes" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL];
}
return self;
}
- (void)dealloc {
[self removeObserver:self forKeyPath:#"selectedRowIndexes"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(#"change: %#", change);
}
#end
However, I never see -observeValueForKeyPath:... get called. Am I missing something?
I'm also open to a better solution - the reason I want to do KVO rather than relying on the delegate's -tableViewSelectionDidChange: method is that I'd like both the previous and current values for selectedRowIndexes, rather than just being able to get the current selection. If there's a way to do that without KVO on this property, I'm all ears.
If you're not seeing KVO notifications, I would open a radar at bugreport.apple.com. The reason is likely that they're not fully KVO compliant. I haven't tested, but I wouldn't be shocked.
As to how to do this without KVO, that's fairly straightforward. Use tableView:willSelectRowAtIndexPath: tableView:shouldSelectRow:. Check the current value, and the value to be added. Return YES.
I had the same problem, and I found the solution :
Bind the NSTableView view Selection Indexes to the array controller, key selectionIndexes
I met a problem about the NSTableView, and it is like:
one datasource of tableview is called:
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return [self.dataArray count];
}
But this one is never called:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
// the code
}
I have checked the the array really had data, and also checked the
[NSTableView reloadData] was called in the main thread.
SO I'm totally lost about this weird problem.
Would any one give some tips?
thanks!
I moved the initial code from awakeFromNib to the init, and it called correctly. But I still don't know the real reason. I guess it matters with the life-cycle of the view because the class which has the tableview is a subclass of NSObject and not of NSViewController.
Greetings I have the following problem trying to set a datasource in an NSComboBox.
This is my custom datasource class:
#interface CComboDatasource : NSObject <NSComboBoxDataSource> {
#private
NSMutableArray* values;
}
#property (nonatomic,retain) NSMutableArray* values;
-(int)itemCount;
#end
#implementation CComboDatasource
#synthesize values;
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
values=[[NSMutableArray alloc] init];
[values addObject:#"A"];
[values addObject:#"B"];
[values addObject:#"C"];
}
return self;
}
- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox
{
return [values count];
}
- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index
{
return [values objectAtIndex:index];
}
- (void)dealloc
{
[values release];
[super dealloc];
}
#end
Later in another file I connect my IBOutlet with my NSComboBox object (c_box) and I set the datasource (CComboDatasource* data_source).
[c_box setUsesDataSource:TRUE];
[c_box setDataSource:data_source];
[c_box setEditable:NO];
After the previous actions nothing is displayed in the combo box, what am I doing wrong?
What you have looks basically right to me. I can think of a few things you could try:
1) Try temporarily replacing "return [values count]" with "return 5" and replacing "return [values objectAtIndex:index]" with "return #"arbitraryString"". If "arbitraryString" then shows up in the combobox, you'll know the problem is with the "values" array.
2) Try initializing the "values" array like this:
values = [NSMutableArray array];
(It's a convenience method offered in NSArray.)
If you stick with an alloc-init method, you should make a separate temporary array that way, assign it to "values," then release it. Otherwise, since you've propertized "values" with "retain," you're retaining it twice.
3) Try adding this line at the end of your c_box calls:
[c_box reloadData];
And any time you change the data source array, call this again.
4) I don't see why separating the data source class from the class controlling the combobox should be a problem, but if it's still not working, try making the window/view controller that owns the combobox outlet the class that implements the NSComboBoxDataSource protocol (the numberOfItemsIn and objectValueFor methods), and either put "values" in this controller class or give this class access to "values."
Hope that helps.
Ok I found the problem ,in order by the custom datasource class to work u need
Create an NSObject and drag it to your editor
Change the type to your custom datasource class
Declare your Datasource as IBOutlet CustomDatasourceClass* myclass
Connect the Object with the previous outlet
Link your NScomboBox datasource (in IB designer) to the CustomDatasourceClass object
I have problem with comboBox:objectValueForItemAtIndex: because I have 10 combo box, every combo box I checking by:
if (aComboBox == _myCombo)
8 combo box works fine, but 2 not. I don't know what I'm doing wrong and why others work. I thinking about this problem about 2 weeks. I'm trying to delete and create new with different steps, but nothing help.
The solution is to reloadData before select option in awake from nib.
[_myCombo reloadData];
I have an NSTableView that contains 2 different Columns - one is an NSImageCell that shows a file icon, and the second is a custom subclass of NSTextFieldCell that contains a quick look button on the right of the text. When I click the Quick Look button, the following code is invoked:
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
This does it's job and shows the blank Quick Look panel saying "No Items Selected." After I did a bit of research on the internet, I implemented a custom NSTableView subclass to be the Delegate and Data Source for the Quick Look panel. I get the notification that Quick Look asks if I want to be the delegate, and I respond with return YES. Even though I implement all methods in both QLPreviewPanelDataSource and QLPreviewPanelDelegate, at runtime I get this error on the console:
2010-12-24 15:32:17.235 BackMeUp[4763:80f] clicked: ~/Desktop/HUDTape.mov
2010-12-24 15:32:17.489 BackMeUp[4763:80f] [QL] QLError(): -[QLPreviewPanel setDelegate:] called while the panel has no controller - Fix this or this will raise soon.
See comments in QLPreviewPanel.h for -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.
2010-12-24 15:32:17.490 BackMeUp[4763:80f] [QL] QLError(): -[QLPreviewPanel setDataSource:] called while the panel has no controller - Fix this or this will raise soon.
See comments in QLPreviewPanel.h for -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.
2010-12-24 15:32:17.491 BackMeUp[4763:80f] We can now receive QL Events.
2010-12-24 15:32:18.291 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
2010-12-24 15:32:18.292 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
And the Quick Look panel does not show up, which I find rather odd. The first line above is just that I know the cell has been clicked. Anyways, here is the .m file of the custom table view subclass:
//
// BackupListTableView.m
// BackMeUp
//
// Created by Tristan Seifert on 12/24/10.
// Copyright 2010 24/7 Server. All rights reserved.
//
#import "BackupListTableView.h"
#implementation BackupListTableView
- (void) awakeFromNib {
}
// Quick Look Delegates
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel;
{
[QLPreviewPanel sharedPreviewPanel].delegate = self;
[QLPreviewPanel sharedPreviewPanel].dataSource = self;
NSLog(#"We can now receive QL Events.");
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel
{
// This document is now responsible of the preview panel
// It is allowed to set the delegate, data source and refresh panel.
[QLPreviewPanel sharedPreviewPanel].delegate = self;
[QLPreviewPanel sharedPreviewPanel].dataSource = self;
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel
{
// This document loses its responsisibility on the preview panel
// Until the next call to -beginPreviewPanelControl: it must not
// change the panel's delegate, data source or refresh it.
return;
}
// Quick Look panel data source
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel
{
return 1;
}
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index
{
int selectedRow = [self selectedRow];
return [NSURL URLWithString:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]];
}
// Quick Look panel delegate
- (BOOL)previewPanel:(QLPreviewPanel *)panel handleEvent:(NSEvent *)event
{
// redirect all key down events to the table view
return NO;
}
// This delegate method provides the rect on screen from which the panel will zoom.
- (NSRect)previewPanel:(QLPreviewPanel *)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item
{
NSRect iconRect = [self rectOfColumn:1];
/*
// check that the icon rect is visible on screen
NSRect visibleRect = [self visibleRect];
// convert icon rect to screen coordinates
iconRect = [self convertRectToBase:iconRect];
iconRect.origin = [[self window] convertBaseToScreen:iconRect.origin];
*/
return iconRect;
}
// This delegate method provides a transition image between the table view and the preview panel
- (id)previewPanel:(QLPreviewPanel *)panel transitionImageForPreviewItem:(id <QLPreviewItem>)item contentRect:(NSRect *)contentRect
{
int selectedRow = [self selectedRow];
NSImage *fileIcon = [[NSWorkspace sharedWorkspace] iconForFile:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]];
return fileIcon;
}
#end
Thanks for any help.
The documentation isn't the best for this, since it's a new feature that was added in 10.6. (Well, there is obviously the class and protocol references, but in my experience, I've always found the Companion Guides to be more helpful in understanding how the objects are intended to be used in a real-world scenario).
The QLPreviewPanelController Protocol Reference defines 3 methods:
QLPreviewPanelController Protocol Reference
The Quick Look preview panel shows previews for items provided by the first object in the responder chain that implements the methods in this protocol. You typically implement these methods in your window controller or delegate. You should never try to modify preview panel state if you’re not controlling the panel.
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel;
- (BOOL)beginPreviewPanelControl:(QLPreviewPanel *)panel;
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel;
I'm guessing that your code should look like this:
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel
{
return YES;
}
You shouldn't be doing anything in that method besides returning YES. acceptsPreviewPanelControl: is sent to every object in the responder chain until something returns YES. By returning YES, that object effectively becomes "the controller". The latter 2 methods are called on the controller object after it returns YES from the first method. So you should only be setting the delegate and datasource in the beginPreviewPanelControl: method (at which time you will be regarded as the current controller).
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel
{
// This document is now responsible of the preview panel
// It is allowed to set the delegate, data source and refresh panel.
[QLPreviewPanel sharedPreviewPanel].delegate = self;
[QLPreviewPanel sharedPreviewPanel].dataSource = self;
NSLog(#"We can now receive QL Events.");
}
First:
-acceptsPreviewPanelControl should only return YES and not try to set delegate and datasource.
Then, the problem is that you get an exception breaking the panel:
2010-12-24 15:32:18.291 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
The exception is very likely caused by these invocations:
[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]
Very likely, [[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] is a file path (a NSPathStore instance which is a subclass of NSString) so it does not respond to -stringValue
So replace:
[NSURL URLWithString:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]]
by:
[NSURL fileURLWithPath:[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow]]
Also remove the call to -stringValue in transitionImageForPreviewItem.
As a side note, it seems to be suboptimal to load the image at each call of transitionImageForPreviewItem. I suppose you already have the image computed elsewhere (displayed in your table view), try to use it.