im new to stackoverflow and objective c, so forgive me in advance :)
i have a UIcollectionView that displays a virtual folder list
when clicking on "Add Folder" a cell is added to the collection. The cell has a UITextField inside that i make FirstResponder, which pops up the virtual keyboard and the user can edit the name of the folder. works good on every folder im adding.
the problem is when the user is tapping a folder.
I do reloadData to the CollectionView (cuz i now wanna show the tapped folder's content) and after that every folder that i add wont pop up the virtual keyboard, and the UITextField wont become first responder ?
anyone has an idea why that is ?
another interesting thing is that when i tap on the collection (an empty area that has no cells) and after that tries to create a new folder, the keyboard returns..
My problem was that my UITextField was on the cell itself, and the fact that UICollectionView is using reusable cells. So every time i got me a different cell (an exisiting one when it was available and a new one when it wasent) and couldnt locate where to send my becomeFirstRisponder. I solved it by giving every cell a uniq identifier at creation time and looking for the right identifier when sending the becomeFirstRisponder command.
Related
I'm a complete n00b with MacRuby and Cocoa, so keep that in mind when answering - I need lots of details and explanation. :)
I've set up a simple project that has 2 windows in it, both of which are built with Interface Builder. The first window is a simple list of accounts using a table view. It has a "+" button below the table. When I click the + button, I want to show an "Add New Account" window.
I also have an AccountsController < NSWindowController and a AddNewAccountController < NSWindowController class, set up as the delegates for these windows, with the appropriate button click methods wired up, and outlets to reference the needed windows.
When I click the "+" button in the Accounts window, I have this code fire:
#add_account.center
#add_account.display
#add_account.makeKeyAndOrderFront(nil)
#add_account.orderFrontRegardless
this works great the first time I click the + button. Everything shows up, I'm able to enter my data and have it bind to my model. however, when I close the add new account form, things start going bad.
if I set the add new account window to release on close, then the second time I click the + button, the window will still pop up but it's frozen. i can't click any buttons, enter any data, or even close the form. i assume this is because the form's code has been released, so there is no message loop processing the form... but i'm not entirely sure about this.
if i set the add new account window to not release on close, then the second time i click the + button, the window shows up fine and it is usable - but it still has all the data that i had previously entered... it's still bound to my previous Account class instance.
what am I doing wrong? what's the correct way to create a new instance of the Add New Account form, create a new Account model, bind that model to the form and show the form, when I click the + button on the Accounts form?
... this is all being done on OSX 10.6.6, 64bit, with XCode 3.2.4
The issue is that it doesn't create the window each time. Release on close is a bit of an annoying option and generally is only used if you know the window controller is also being released when the window closes. (Note I've never used MacRuby so I'll be giving code in Obj-C as I know that it is correct, hopefully you can convert it. I'll be assuming GC is on as it should be with MacRuby).
Now there are two ways to do this. I'm not entirely sure how your NIB/classes are set up as it could be one of two ways.
--
The first way to solve it is to use the outlets you use to reference the form elements to blank them out when you display the window again eg [myTextField setStringValue:#""]. If you're using cocoa bindings then it's a little trickier, but basically you have to make sure the bound object is blanked out. I would recommend against bindings though if you are new to Cocoa.
--
The second way is to make the AddNewAccountController class a subclass of NSWindowController. When you press the + button you would then create a new instance of it and display it (remember to store it in an ivar). The best way to do it would be as so:
if (!addAccountController) {
addAccountController = [[AddNewAccountController alloc] initWithWindowNibName:#"AddNewAccountController"];
[[addAccountController window] setDelegate:self];
}
[addAccountController showWindow:self];
This prevents a new instance being made if the window is already visible. You then need to implement the delegate:
- (void)windowWillClose:(NSNotification *)notification {
//If you don't create the account in the AddNewAccountController then do it here
addAccountController = nil;
}
Obviously you would need to move the window to a separate NIB called "AddNewAccountController". In this NIB make sure to set the class of the File's Owner to AddNewAccountController and then to connect the File's Owner's window outlet to the window.
When all this is set up, you will get a fresh controller/window each time. It also has the benefit of splitting up nibs and controllers into more focused units.
--
One last thing. While it is fine to do something like this in a window, you may want to eventually look at doing this via a sheet, as it would then prevent the possibility of the add account window getting hidden behind other windows.
Im wanting to create a generic dropdown control for my IPad app. Basically when the user clicks on a textfield a popover control will show and list items. The users can keep typing in the textfield which will filter the items in the dropdown popover control.
Has anyone got any advice or know of any examples on accomplishing this?
Basically it will be like the "Suggestions" popover list in the App store search field of the ipad.
Thanks in advance
Well, I would accomplish this by loading a TableViewController into the PopoverController and make its interface available to the ViewController (the one that has the textfield in it).
In the TableViewController I would load a dictionary/array of items. Whenever a user enters text in the textfield (you can respond on this trough events in your Interface Builder) I would then call a function in the TableViewController that updates the list that is displayed (e.g. displays all dictionary items that start with the entered text).
Whenever someone clicks on a item in TableViewController, you can then call a function in the ViewController.
I can't give you a code sample, since that would require quite some time to create :P.
I hope this helps you.
I have a question regarding the importance of choosing the correct starting and ending points of a control-drag operation while setting actions using Interface Builder (3.2.3). This issue came up while working through an example in an introductory text. In the example project there is a very simple graphical window with a three NSTextFields (i.e. First Name, Last Name, Email) and one NSTextView. The interface for the controller class is declared in the header file as:
#interface EmailController : NSObject {
IBOutlet NSTextField *emailField;
IBOutlet NSTextField *firstNameField;
IBOutlet NSTextField *lastNameField;
IBOutlet NSTextView *resultTextView;
}
- (IBAction)textFieldChanged:(id)sender;
#end
The text makes a point in stating that when setting an action you begin the control-drag at the control. Specifically, the example starts with a control-drag from the First Name editable NSTextField text field to the EmailController instance where a small black window appears and where the action textFieldChanged action can be selected.
After the First Name editable box is connected to the action the text directs the reader to also connect the Last Name and Email editable boxes to the same action. However in these cases the text directs the reader to start the control-drag operation from the small circle to the right side of the textFieldChanged action in the black window of the controller instance and to end at the Last Name and Email editable boxes. This seems opposite to how I understand the general rule of starting at the control while setting an action.
No matter which points I choose as my start and my end I seem to get the same result. The actions listed in the Connector Inspector for the various objects always seem indifferent to which point I choose as my start. I wouldn't even consider it an issue if it wasn't that it seemed contradictory to the explicitly stated general rule. I did notice a problem when I tried doing the same thing with outlets.
Does it matter which point you choose as the start when connecting a control to an action?
Thanks
Does it matter which point you choose as the start when connecting a control to an action?
No.
Big Nerd Ranch recommends always dragging from sender to receiver (outlet to object or control to target) to make clear which direction the message(s) will go in. It's equally valid to drag in the other direction, but does not reinforce the message direction to new Cocoa and Cocoa Touch programmers.
(To be clear, that blog is authored by a former BNR class attendee, not by BNR or anyone working for BNR.)
After the First Name editable box is connected to the action the text directs the reader to also connect the Last Name and Email editable boxes to the same action. However in these cases the text directs the reader to start the control-drag operation from the small circle to the right side of the textFieldChanged action in the black window of the controller instance and to end at the Last Name and Email editable boxes. This seems opposite to how I understand the general rule of starting at the control while setting an action.
One advantage of the right-click-on-action-receiver-and-drag-from-the-actions way is that it's easier to connect a bunch of actions at once. That sounds like the best reason for the tutorial making an exception there, aside from just being by a different author or authors (I'm guessing) with a different way of doing things.
I have a simple Core Data app I am building to try to understand Core Data. It has two entities: a weather station, and a collection of observations for a given station.
I created the initial interface for this by putting a tab view on my window, selecting the first tab, and dragging the weather station entity onto that view; then selecting the second tab and dragging the observations entity onto the second tab.
I then created a third tab myself and added a popup at the top. This popup is bound to the StationArrayController, so it populates with all the weather stations I add. This works great.
I then added a table view to display the Observations associated with the selected Station. This also works great. I implemented this with a method that creates a predicate that searches for all observations whose station matches the selected station, and attached the predicate to the ObservationArrayController associated with the Table View on the third tab. (I couldn't figure out how to do this in IB, so I did it programmatically).
The bug is this: If I load a previously saved file with weather stations and observations in it, when I go to the third tab, even though one of the stations is selected (ie, it appears in the popup), all of the observations appear in the tableview, not just the ones associated with that station.
This is happening because I am not calling the method to attach the predicate to the Observation Array Controller until I actually use the popup to change the station manually.
So my problem and question is this (sorry it took so long to get to this point!): How can I detect when the tab view has loaded so I can force the method which attaches the predicate to run and thus have an initial list of Observations which matches the selected Station?
I tried creating a custom View class and subclassing it for the third tab view and putting this code in the awakeFromNib method, but this is too early in the process (the "selected station" is -1 at this point in the loading process).
Any help would be much appreciated. thank you!!
Elisabeth
Ah, I just answered my own question!
I set the delegate of the tabview to MyDocument, and implemented tabView:didSelectTabViewItem: there. I created an IBOutlet in MyDocument pointing to the third tab view, and in this method, checked to see if the third tab was selected, and if so, called the method to attach the predicate to the ObservationArrayController. Works great!
I have been trying this for past few days but couldnt figure it out.
I have an application which has a NSOutlineView and a NSTableView. Outlineview takes input a path and displays them in the form of a tree structure its sub contents. So when ever a user clicks on a particular folder in the outine view, the contents of the folder should be displayed in the table view with their attributes in the form of a list.
Now i am able to display in both the views respective contents and the interaction between the outlineview and tableview is done using delegates and notifications.
Now my problem is I want to have mouse events to be detected in both the views so that i can make my app more interactive by enabling single click to select, double click to enable opening the file/folder and control+click to enable a contextual pop up menu. but strangely no mouse events are getting detected.
my design of the app is pretty simple with each of table and outline views having their own view and controller class and interactions between them using notifications. Please can you guys suggest me where i am going wrong?
I know i can get single click and double click to work using setAction and DoubleAction methods of table view but i cannot get control click to work. I want to know whats wrong with my app design as non of my views are detecting mouse events :(
Thanks
You can get whether Control is pressed with:
if([[NSApp currentEvent] modifierFlags] & NSControlKeyMask){
//control was pressed at the time the event was posted
}
Or you might want to subclass the NSTableView/NSOutlineView and override mouseDown: to get the event directly.
Also, if your action and doubleAction aren't working, verify that the target/action are correct with something like:
NSAssert([[theView target] respondsToSelector:[theView doubleAction]], #"target/action is wrong");