Best practice to pass a value from pop over control on iPad - objective-c

It is an iPad app based on SDK 3.2.
I have a MainUIView, that is subclass from UIView, it have a UIButton and a UILabel. When user press the UIButton, the pop over control will be appeared with a table view. When the user select a cell from the table view, the UILabel changes content base on the user click, and the pop up table view will disappear.
The question is, how can I pass the "selected cell" to the UILabel. I am thinking making a "middle man" object. When the user click the UIButton, and the "middle man" will pass to the table. When the cell is selected, the "middle man" will store the idx, and call the UILabel change content from the value of "middle man".
But I think it is pretty complex to implement, is there any easier way to implement it? thz u.

The standard way to do this is to call a delegate method when the popover closes with a selected value. The method will have been created on the view controller that calls the popover and handles setting the value.
In your view controller:
- (void) popoverDone:(id)sender {
label.text = [sender someValue];
[sender dismissPopoverAnimated:YES];
}
And in the popover:
- (void)tableView:tableView didSelectRowAtIndexPath:indexPath {
[delegate performSelector:#selector(popoverDone:) withObject:self];
}
There are other ways of doing this, but the principle is the same.

Related

Object under mouseDown COCOA

I have a pretty simple question for which I could not find a simple answer.
When using cocoa (osx, xcode) and a method called "mouseDown" which detects if mouse has clicked on a view, how to detect on which object mouse has clicked? I just need a class name so I can know if the user has clicked on, for example NSImageView, WebView, NSTextView or on a NSView it self? Or even better, if I have two NSImageViews on my NSView, how to detect on which one it was clicked?
Cheers.
In your view mouseDown method, you can call the hitTest: method to get the farthest descendant of the receiver in the view hierarchy that was clicked:
So in your view subclass, you could do something like:
- (void)mouseDown:(NSEvent *)theEvent
{
id clickedObject = [self hitTest:[theEvent locationInWindow]];
if ([clickedObject isKindOfClass:[NSImageView class]]) {
NSLog(#"Clicked an ImageView");
} else if ([clickedObject isKindOfClass:[WebView class]]) {
NSLog(#"Clicked a WebView");
}
}
Your question seems a bit odd though, because normally you don't need to do this hit testing yourself.
If you're trying to get a click event when a particular image is clicked, a better way would be to use a borderless button with an image set and then implementing an action method and connecting that to the button.

Show NSWindow on right click in NSTableView

I'd like to display an NSWindow when right clicking an item in an NSTableView, similarly to how the available outlets are shown in Interface Builder when you right click an object:
Unfortunately you can only use an NSMenu subclass as the menu property.
I also didn't find a delegate method of NSTableView that notifies about right clicks.
I was able to subclass NSTableView and implement rightMouseDown: and rightMouseUp: to be notified about those events, but if I set the menu property of the row cells to nil, they are not highlighted when right clicked, even though I call the super implementation):
- (void)rightMouseDown:(NSEvent *)theEvent {
[super rightMouseDown:theEvent];
NSPoint eventLocation = [theEvent locationInWindow];
eventLocation = [self convertPoint:eventLocation fromView:nil];
NSInteger rowIndex = [self rowAtPoint:eventLocation];
NSLog(#"Right clicked at row index %d", rowIndex);
}
I would like to have the highlight effect in the image below but display a window instead of the context menu:
First for the right click: explicitly select the row on right click (e.g. via this message). Then create your own NSWindow descendant, set an own NSView class as contentView and in the view you can draw the black background, rounded borders and what not. Show this window in your right click handler.
You can use an NSPopover, which works quite nicely. A popover creates a window for you, even if it is somewhat hidden. You'll get it from your controls if you send them the window message, and can register to listen for events, for instance.
The whole popover can be created in IB, and just have to implement the showRelativeToRect:ofView:preferredEdge: method in code.
To catch the right click event, you can use rightMouseDown:, which is originally defined in NSResponder, but is overridden in NSView to simply catch the event and show menu and it doesn't pass the event upwards in the responder chain (or the inheritance chain, for that matter). Hence, you simply implement that method to call showRelativeToRect:ofView:preferredEdge:.
You will typically need to have the contents in an NSViewController and its own accompanying nib file.
The NSPopover's contentViewController property can be set in IB, too.
All in all, not much code needed.
This tutorial is useful.

UISearchBar with ScopeBar in Modal Form Sheet

My ViewController is a custom UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>. I have set up the UISearchBar to display a scope bar.
I instantiate the view controller once and then show the same view on demand via [self presentModalViewController:mySearchController fromView:self.view];
Now, when I configure the view controller to be displayed as a form sheet, the scope bar appears only the first time the view is shown. The next time the scope bar is not displayed.
Displaying the view as a page sheet works fine. However in this case I observe that the first time the scope bar is already in place, while thereafter it is animated into the search bar as soon as it becomes the first responder.
I fiddled around with the view and controller settings in the inspector without any success.
What is causing this behavior?
How can I make the scope bar appear in the form sheet the next time I am showing the view?
Is there a way to prevent the UISearchBar from going into a different state when its view is hidden/redisplayed?
Set the scope bar titles in search delegate for begin editing and make it nil when the search ends. And add the showScopeBar method right after this method. Try and check if that helps.
For eg:-
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
[searchBar setScopeButtonTitles:[NSArray arrayWithObjects:#"Title1", #"Title2", nil]];
[searchBar setShowsScopeBar:YES];
//...
}
And in didEndEditing,
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[searchBar setScopeButtonTitles:nil];
[searchBar setShowsScopeBar:NO];
//..
}
In addition to this, whenever you want to display the scopebar you can use the above lines to show and hide it.

Xcode - setFocus on a text field, becomeFirstResponder isn't enough

At the moment, I trigger a method on 'Did End On Exit' in my app (I'm aware that this may not be the greatest way of doing it but I'm very new to Objective C and Xcode for that matter and I'm simply doing what feels comfortable to me).
This method resigns the firstResponder from the current text field and applies it to a later text field.
The problem I'm facing is that the keyboard covers the next text field so that the use has no idea where the focus is and therefore what they are required to type.
How do I get it so that my keyboard shifts down and actually shows the text box that is currently active? Making something the firstResponder simply doesn't do what I want it to, unless there's part of the implementation I'm missing.
Here's my simple method:
- (IBAction)firstNameNext:(id)sender {
[firstNameTextField resignFirstResponder];
[surnameTextField becomeFirstResponder];
}
Any advice would be super.
Add UIScrollView in your main view then all contents as subview to UIScrollView
Now when specific UITextField needs to be able to visible in view use its delegate like this:
Note: add UITextFieldDelegate in .h file like this
#interface yourViewController : UIViewController<UITextFieldDelegate>
Also bind with File's Owner
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
{
if(textField == yourSpecficTextField) //one u want move upwards
{
yourScrollView.contentOffset = CGPointMake(0,200); //required offset
}
... //provide contentOffSet those who needed
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
yourScrollView.contentOffset = CGPointMake(0,0); //make UIScrollView as it was before
}
If you have keyboard input fields that will be covered by the virtual keyboard, then you need to move those fields out from under the virtual keyboard.
The normal way to do this is to have the controller's view be a scrollable view like UIScrollView. Moving Content That Is Located Under the Keyboard gives a very robust way of adjusting your scroll view and ensuring the required field shows.

How to make a custom tableView cell accessory

I have not yet found any really good examples on how to do this. There is an image that I want to use as the accessory button and when I put it in and click on it doesn't work. So it looks correct but doesn't work...
Here is my code:
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
cell.accessoryView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"TableView_Green_Disclosure.png"]];
So how do I get my UIImageView to call accessoryButtonTappedForRowWithIndexPath whenever it is tapped?
A thorough reading of accessoryView and accessoryType would reveal that they are mutually exclusive ways to customize a cell.
Setting the accessoryType will cause the table view delegate method to be called when it is tapped.
Setting the accessoryView will ignore the setting of accessoryType and give you something to display. If you want to receive a callback from the custom view you've put in place, it should be a control that is wired up to do so. (Or any view with a gesture recognizer.)
If you use a button, and set its action to accessoryTapped:, you will receive the button as the "sender" argument. You can walk up the view hierarchy until you find a table view cell, and then ask your table view what the indexPath of that cell is. This will then get you an index into your model objects and you be able to act on it appropriately.
Alternate to the button, you can enable interaction on the UIImageView above, and add a gesture recognizer to it.
To make the button actually do something, you'll need to implement - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath from UITableViewDelegate.
When an accessory button is tapped in a row, this method will be called and you'll have the chance to act appropriately using the passed in index path to determine which row's accessory was tapped.
Check the blog post hdr->cmdline for creating custom accessory view for UITableView.
The author used UIButton objects with images for custom accessory view.
To make use of the accessoryView - you would need to set the cell's accessoryType to UITableViewCellAccessoryNone deposit a UIButton (with associated image) into the cell and then wire it up to receive user touches. You might use something like the code below as the IBAction response to the cell's UIButton being touched:
- (IBAction) accessoryButtonPressed:(id) sender
{
NSUInteger pathInts[] = { 0,0 };
pathInts[1] = self.currentselectedrow; // ivar set when tableview row last selected
NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:pathInts length:2];
[self tableView:mytableview accessoryButtonTappedForRowWithIndexPath:indexPath];
}
The UIButton would be wired to execute this glue code by way of a line inside your tableview's "cellForRowAtIndexPath:" function
[thecell setButtonTarget:self action:#selector(accessoryButtonPressed:)];
One thing I noticed is that the UIButton seems to want a 'swipe right' versus a simple 'tap' touch in order to trigger the event - but it could be my beta iOS that's the problem. Note that I had added a UIButton* object named 'cell_accessoryButton' to the Custom Cell source.
In the cell's source you'd support the 'setButtonTarget' call with code like this:
- (void) setButtonTarget:(MyViewController*)inTarget action:(SEL) inAction
{
[self.cell_accessoryButton addTarget: inTarget
action: (SEL) inAction
forControlEvents: UIControlEventTouchUpInside];
}
It's so much easier to just use the accessoryType reference and let iOS do the heavy lifting - but, if you want a custom graphic, etc - this is another path that works.