I have created an NSSearchField that stores a list of recent searches. The search field is connected to a method that updates a label in the window with the text typed into the search field. The problem is that the label updates as soon as the user types into the search field, I need the label to not update until after the user types the text then hits the Enter key. I can do this with the typical NSTextField but I want to use the NSSearchField so I can show recent searches. Please see my code below and offer some suggestions. Thanks.
Interface file:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
#property (weak) IBOutlet NSSearchField *searchField;
#property (weak) IBOutlet NSTextField *textField;
- (IBAction)searchString:(id)sender;
#end
Implementation file:
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize searchField, textField;
- (void)awakeFromNib {
if ( [searchField respondsToSelector:#selector(setRecentSearches:)] ) {
NSMenu *searchMenu = [[NSMenu alloc] initWithTitle:#"Search Menu"];
[searchMenu setAutoenablesItems:YES];
NSMenuItem *recentsTitleItem = [[NSMenuItem alloc] initWithTitle:#"Recent Searches" action:nil keyEquivalent:#""];
[recentsTitleItem setTag:NSSearchFieldRecentsTitleMenuItemTag];
[searchMenu insertItem:recentsTitleItem atIndex:0];
NSMenuItem *norecentsTitleItem = [[NSMenuItem alloc] initWithTitle:#"No recent searches" action:nil keyEquivalent:#""];
[norecentsTitleItem setTag:NSSearchFieldNoRecentsMenuItemTag];
[searchMenu insertItem:norecentsTitleItem atIndex:1];
NSMenuItem *recentsItem = [[NSMenuItem alloc] initWithTitle:#"Recents" action:nil keyEquivalent:#""];
[recentsItem setTag:NSSearchFieldRecentsMenuItemTag];
[searchMenu insertItem:recentsItem atIndex:2];
NSMenuItem *separatorItem = (NSMenuItem*)[NSMenuItem separatorItem];
[separatorItem setTag:NSSearchFieldRecentsTitleMenuItemTag];
[searchMenu insertItem:separatorItem atIndex:3];
NSMenuItem *clearItem = [[NSMenuItem alloc] initWithTitle:#"Clear" action:nil keyEquivalent:#""];
[clearItem setTag:NSSearchFieldClearRecentsMenuItemTag];
[searchMenu insertItem:clearItem atIndex:4];
id searchCell = [searchField cell];
[searchCell setMaximumRecents:20];
[searchCell setSearchMenuTemplate:searchMenu];
}
}
- (IBAction)searchString:(id)sender {
[textField setStringValue:[searchField stringValue]];
}
#end
If you don't want to do it in code, view your nib file, select the search field and choose "Sends whole search string"
Like So:
Hope this helps!
You need to use [searchField.cell setSendsWholeSearchString:YES]
Related
I want a dynamically submenu. Now I tried this way:
#interface AppController()
#property(strong) Accounts * accView;
#property (weak) IBOutlet NSMenuItem *serverMenu;
#end
#implementation AppController
-(void)awakeFromNib {
_accView = [[Accounts alloc] initWithNibName:#"Accounts" bundle:nil];
[self.viewk addSubview:[_accView view]];
[[_accView view] setFrame:self.viewk.bounds];
NSMenuItem * testItem = [[NSMenuItem alloc] initWithTitle:#"Test" action:#selector(test:) keyEquivalent:#""];
[[_serverMenu submenu] addItem:testItem];
}
- (void)test:(id)test {
}
Then it get's added but I can't click on it. It's like this:
How can enable it?
You also need to assign a target to your NSMenuItem, like
[testItem setTarget:self];
I have 2 methods that add the Previous, Next & Done toolbar above the iOS Keyboard and handle these actions. I'm looking for a way to code these methods once and reuse it across multiple UITableViewControllers. (DRY Code)
I find myself copy and pasting these methods into each UITableViewController. If I make a small change, I have to copy and pastes that change everywhere. The code below is just an example, I seem to be repeating myself a lot in my code.
Here's an example of the code I'd like to reuse:
- (void) createInputAccessoryView
{
_inputAccView = [[UIView alloc] initWithFrame:CGRectMake(10,0,310,42)];
UIToolbar *keyboardToolbar = [[UIToolbar alloc] init];
keyboardToolbar.barStyle = UIBarStyleBlackTranslucent;
[keyboardToolbar sizeToFit];
_segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Previous", #"Next", nil]];
[_segmentedControl setSegmentedControlStyle:UISegmentedControlStyleBar];
[_segmentedControl addTarget:self action:#selector(nextPrevious:) forControlEvents:UIControlEventValueChanged];
UIBarButtonItem *nextPrevButton = [[UIBarButtonItem alloc] initWithCustomView:_segmentedControl];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyboard)];
NSArray *barItems = [NSArray arrayWithObjects:nextPrevButton, flexSpace, doneBtn, nil];
[keyboardToolbar setItems:barItems];
[_inputAccView addSubview:keyboardToolbar];
}
- (void) nextPrevious:(id) sender
{
switch(_activeTxtField.tag) {
case 1:
//Recipe Name
if (_segmentedControl.selectedSegmentIndex == 1){
[_descriptionTextField becomeFirstResponder];
_activeTxtField = _descriptionTextField;
}
break;
case 2:
//Recipe Description
if (_segmentedControl.selectedSegmentIndex == 0){
[_nameTextField becomeFirstResponder];
_activeTxtField = _nameTextField;
}
default:
break;
}
}
Create a custom UIView that defines the common input accessory view. Should include a definition of a delegate to allow the class using the accessory view to handle, for example, previous/next button taps as appropriate. Here's a header file example for a keyboard accessory view:
#import <UIKit/UIKit.h>
#class KeyboardAccessoryView;
#protocol KeyboardAccessoryViewDelegate <NSObject>
-(void)accessoryNext:(id)sender;
-(void)accessoryPrevious:(id)sender;
#end
#interface InputAccessoryView : UIView
#property (nonatomic, weak) id<KeyboardAccessoryViewDelegate> delegate;
#property (nonatomic, setter = enablePrevious:) BOOL previousEnabled;
#property (nonatomic, setter = enableNext:) BOOL nextEnabled;
-(id)initPreviousNextAccessory;
#end
Edit - showing details of use in a UIViewController.
The .h file:
#import <UIKit/UIKit.h>
#import "KeyboardAccessoryView.h"
#interface MyViewController : UIViewController <KeyboardAccessoryViewDelegate>
//...
#end
The .m file:
#import "MyViewController.h"
#interface MyViewController () {
KeyboardAccessoryView *inputAccessoryView;
}
#end
#implementation MyViewController
//...
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
inputAccessoryView = [[KeyboardAccessoryView alloc] initPreviousNextAccessory];
inputAccessoryView.delegate = self;
//...
}
-(void)accessoryNext:(id)sender{
// handle Next
}
-(void)accessoryPrevious:(id)sender{
// handle Previous
}
//...
#end
Here is my code :
// View Controller with navigation bar
InAppPurchaseViewController *purchaseViewController = [[InAppPurchaseViewController alloc] init];
purchaseViewController.title = #"Magasin";
purchaseViewController.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissViewController:)] autorelease];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:purchaseViewController] autorelease];
// Add `purchaseViewcontroller` TO container AND container ON openGLView
UIViewController *container = [[UIViewController alloc] init];
[container setView:[[CCDirector sharedDirector] openGLView]];
[container setModalTransitionStyle: UIModalTransitionStyleCoverVertical];
[container presentViewController:navController animated:YES completion:nil];
The UITableView is in purchaseViewController.
I was thinking of using [UIColor clearColor], BUT whatever I use it on I get a BLACK background on my UITableView. The cells get unselectable and unslidable (apart from the elements that are into the cells)
EDIT : The appdelegate
Here is the .h
#class AudioEngine;
#class RootViewController;
#class Score;
#interface AppDelegate : NSObject <UIApplicationDelegate, GameCenterManagerDelegate>
#property int CurrentPackage;
#property int CurrentScore;
#property int CurrentHighScore;
#property BOOL SoundShouldPlay;
#property BOOL PauseScreenUp;
#property(nonatomic, retain) AudioEngine *CustomAudioEngine;
#property(nonatomic, retain) GameCenterManager *CustomGameCenterManager;
#property(nonatomic, retain) UIWindow *window;
#property(nonatomic, readonly) RootViewController *ViewController;
#property(nonatomic, retain) NSString* CurrentLeaderBoard;
#property(nonatomic, retain) NSMutableArray *TenLastScoresArray;
+(AppDelegate *)get;
-(void)connectToGameCenter;
-(void)addScoreToLastScore:(Score*)score;
And the method did finish launching
-(void)applicationDidFinishLaunching:(UIApplication*)application
{
CC_DIRECTOR_INIT();
self.CurrentLeaderBoard = kLeaderboardID;
[[SKPaymentQueue defaultQueue] addTransactionObserver:[InAppPurchaseSingleton sharedHelper]];
[AudioEngine preloadBackgroundMusic];
[AudioEngine playBackgroundMusic:3];
self.SoundShouldPlay = YES;
[SceneManager goSplash];
}
Instead of presenting the view controller on container:
UIViewController *container = [[UIViewController alloc] init];
...
[container presentViewController:navController animated:YES completion:nil];
what should work is presenting it on the root view controller that the cocos2D template created for you. It is normally accessible through the app delegate:
UIViewController *rootViewController = (UIViewController*)[(YOURAPPDELEGATE*)[[UIApplication sharedApplication] delegate] viewController];
[rootViewController presentViewController:navController animated:YES completion:nil];
viewController is an ivar that the cocos2D default template add to the application delegate class. It is normally private, so you will need to define an accessor:
#property (nonatomic, readonly) RootViewController *viewController; //-- .h file
#synthesize viewController; //-- .m file
Hope this helps.
EDIT:
Based on what I have in my app delegate, I think you could try and instantiate the RootViewController like this:
CC_DIRECTOR_INIT
ViewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
ViewController.wantsFullScreenLayout = YES;
[ViewController setView:[[CCDirector sharedDirector] openGLView]];
...
I have a NSMenuItem with a custom view. However, when I want to update the first row in the menu it add the content as it is in the xib file, not as I set it.
My code:
AppDelegate.m:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
_helper = [[Helper alloc] init];
statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[statusItem setMenu:self.statusMenu];
[statusItem setTitle:#"GravAccount"];
[statusItem setHighlightMode:YES];
_gravatarLoader = [[GravatarLoader alloc] initWithTarget:self andHandle:#selector(setGravatarImage:)];
// Get email address
_email = [_helper getEmailAddress];
if (_email != nil)
{
[_gravatarLoader loadEmail:_email withSize:50.0];
}
}
- (void)setGravatarImage:(NSImage*)image
{
NSLog(#"Image loaded!");
GravatarMenuItem *menuItem = [[GravatarMenuItem alloc] initWithNibName:#"GravatarMenuItem" bundle:nil];
[menuItem.label setTitle:_email];
[menuItem.imageView setImage:image];
NSLog(#"Email: %#", _email);
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:#"" action:nil keyEquivalent:#""];
[item setView:menuItem.view];
[self.statusMenu removeItemAtIndex:0];
[self.statusMenu insertItem:item atIndex:0];
}
GravatarMenuItem.h:
#import <Cocoa/Cocoa.h>
#interface GravatarMenuItem : NSViewController
#property (nonatomic, strong) IBOutlet NSImageView *imageView;
#property (nonatomic, strong) IBOutlet NSTextFieldCell *label;
#end
The outlets are linked in the XIB file on the file's owner.
This is the result:
Log:
2012-03-09 16:57:24.314 appName[51158:403] Image loaded!
2012-03-09 16:57:24.316 appName[51158:403] Email: Paul#******.se
Result:
When you do:
GravatarMenuItem *menuItem = [[GravatarMenuItem alloc] initWithNibName:#"GravatarMenuItem" bundle:nil];
It only creates the view controller. It doesn't actually load the view from the nib. When you access the properties, they are most likely nil as the view has not been loaded (and the connections have not been made).
If you update your code to the following, everything should work fine:
GravatarMenuItem *menuItem = [[GravatarMenuItem alloc] initWithNibName:#"GravatarMenuItem" bundle:nil];
[menuItem view]; // load the view from the nib
[menuItem.label setTitle:_email];
[menuItem.imageView setImage:image];
I tried to find an answer on the internet (this site too), but i cant find the correct answer.
Im trying to give a button an animation, so I used the QuartzCore Framework. But every time I want to play-test it, it gives me this annoying massage: no declaration of property 'newGameButton' found in the interface. I dont know what I did wrong or what I have to do now.
Here is my .h and .m file:
.h file:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface MainMenuViewController : UIViewController {
IBOutlet UIButton* newGameButton;
IBOutlet UIButton* statsButton;
IBOutlet UIButton* settingsButton;
CAKeyframeAnimation* popAnimation;
}
-(IBAction) newGame:(id)sender;
-(IBAction) showStats:(id)sender;
-(IBAction) showSettings:(id)sender;
#end
.m file:
#import "MainMenuViewController.h"
#import "TrafficAppDelegate.h"
#import "TrafficViewController.h"
#implementation MainMenuViewController
-(IBAction) newGame:(id)sender{
TrafficViewController* traffic = [[TrafficViewController alloc] initWithNibName:#"TrafficViewController" bundle:nil];
[self.navigationController pushViewController:traffic animated:NO];
}
-(IBAction) showStats:(id)sender{
}
-(IBAction) showSettings:(id)sender{
}
#synthesize newGameButton, statsButton, settingsButton; (This is the error causer!)
-(void)viewDidLoad{
[super viewDidLoad];
popAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.scale"];
popAnimation.keyTimes = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.7], [NSNumber numberWithFloat:1.0], nil];
popAnimation.values = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.01], [NSNumber numberWithFloat:1.1], [NSNumber numberWithFloat:1.0], nil];
[popAnimation retain];
}
-(void)popView:(UIView*)view{
[view setHidden:NO];
[[view layer] addAnimation:popAnimation forKey:#"transform.scale"];
}
-(void)viewWillAppear:(BOOL)animated{
[popAnimation setDuration:0.3];
[newGameButton setHidden:YES];
[statsButton setHidden:YES];
[settingsButton setHidden:YES];
[self performSelector:#selector(popView:) withObject:newGameButton afterDelay:0.25];
[self performSelector:#selector(popView:) withObject:statsButton afterDelay:0.3];
[self performSelector:#selector(popView:) withObject:settingsButton afterDelay:0.35];
}
#end
I am totally clueless, so please help!
The error is self-descriptive - you need to declare properties you synthesize in class interface, e.g.:
#interface MainMenuViewController : UIViewController {
...
}
...
#property (nonatomic, retain) IBOutlet UIButton* settingsButton;
#end
I'd suggest (Re-)reading about properties in Objective-c reference docs
You're trying to access a property that simply does not exist.
Look at your #interface, do you see any #property declarations?
This will work:
#interface MainMenuViewController : UIViewController {
IBOutlet UIButton* newGameButton;
IBOutlet UIButton* statsButton;
IBOutlet UIButton* settingsButton;
CAKeyframeAnimation* popAnimation;
}
#property (nonatomic, retain) IBOutlet UIButton *newGameButton, *statsButton, *settingsButton;