I am using Objective-C to make an iOS SpriteKit "GameScene" file.
I have an SKLabelNode and a UITextField to input a player's name.
How can I make whatever the UITextField value equals to change the SKLabelNode to say "Thanks," + UITextField value?
(my code) :
#import "GameScene.h"
#implementation GameScene
-(void)didMoveToView:(SKView *)view {
// Use Objective-C to declare all SpriteKit Objects
// inside the {parameters} of "didMoveToView" method:
// SKLabelNodes (SpriteKit Object) display "text".
// Objective-C object named *winner = SKLabelNode (SpriteKit Object)
SKLabelNode *winner = [SKLabelNode labelNodeWithFontNamed:#"Tahoma"];
winner.text = #"You Win!";
winner.fontSize = 65;
winner.fontColor = [SKColor blueColor];
winner.position = CGPointMake(500,500);
[self addChild:winner];
// UITextFields (SpriteKit Object) allow "text" input from users.
// Objective-C object named *textField = UITextField (SpriteKit Object)
UITextField *textField = [[UITextField alloc]
initWithFrame:CGRectMake(self.size.width/2, self.size.height/2+20, 200, 40)];
textField.center = self.view.center;
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.textColor = [UIColor blackColor];
textField.font = [UIFont systemFontOfSize:17.0];
textField.placeholder = #"Enter your name here";
textField.backgroundColor = [UIColor whiteColor];
textField.autocorrectionType = UITextAutocorrectionTypeYes;
textField.keyboardType = UIKeyboardTypeDefault;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
[self.view addSubview:textField];
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}
#end
You need to use a delegate method. Specifically
- (void)textFieldDidEndEditing:(UITextField *)textField;
to do this when you create your textFeild add this line of code
[textfield setDelegate:self]
also to add in that you fallow the delegate in you .h file
#interface ViewController : UIViewController <UITextFieldDelegate>
then when that code gets called you would say inside the method
SKLabelNode = [NSString stringWithFormat:#"Thanks %#",textField.text]
Related
I have a UITextField and I want it has a maximum text length of 20. So I let self(the current view controller) agree to <UITextFieldDelegate> and set self as the text field's delegate, and use the following method to set a maximum length:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.nickNameTextField)
{
if (textField.text.length > 20)
return NO;
}
return YES;
}
However when I insert a breakpoint in this function I found that this function wasn't called when I typed in any words, much less when the text's length exceeds 20. Can somebody tell me why?
You probably haven't linked your textfield with the delegate
Right click on textField which you want to have delegated and drag the textField on the viewcontroller and drop to select the delegate.
I show you steps and screenshot for connecting textField and delegate with XIB or Storyboard.
In storyboard
STEP 1: Click the TextField
STEP 2: Drag the TextField to ViewController
STEP 3: Click "control+mouse" on TextField to ViewController.h and line shows
STEP 4:Now Box will appear and give the TextField Name
STEP 5:Right Click the TextField in ViewController
STEP 6:Hook Up the Delegate to ViewController
If you want to programmatically create the textField
UITextField *txtfldMaxLength = [[UITextField alloc] initWithFrame:CGRectMake(30, 100, 250, 50)];
txtfldMaxLength.borderStyle = UITextBorderStyleRoundedRect;
txtfldMaxLength.textColor = [UIColor blackColor];
txtfldMaxLength.backgroundColor = [UIColor clearColor];
txtfldMaxLength.font = [UIFont systemFontOfSize:17];
txtfldMaxLength.placeholder = #"enter something";
txtfldMaxLength.autocorrectionType = UITextAutocorrectionTypeNo;
txtfldMaxLength.keyboardType = UIKeyboardTypeDefault;
txtfldMaxLength.returnKeyType = UIReturnKeyDone;
txtfldMaxLength.clearButtonMode = UITextFieldViewModeWhileEditing;
txtfldMaxLength.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
txtfldMaxLength.delegate = self;
[self.view addSubview:txtfldMaxLength];
Well I've figured out the problem. I use this grammar to instantiate a UITextField:
self.nickNameTextField.delegate = self;
self.nickNameTextField = ({
UITextField *textField = [UITextField new];
textField.placeholder = [BBTCurrentUserManager sharedCurrentUserManager].currentUser.nickName;
textField.textAlignment = NSTextAlignmentLeft;
textField.backgroundColor = [UIColor lightGrayColor];
textField;
});
Originally I set the textField's delegate outside the braces(like the code above). But when I move self.nickNameTextField.delegate = self;inside the braces then it worked. However I have no idea about why this happened, can someone tell me why?
I want to create following rating views shown below. How is it possible to do it
I have got 3 conditions.I have got label in top and below that are stars and at the end there is TextField. Good,Amazing,Horrific is set according to number of stars. When there is 1 Star i.e horrific condition we have to present four button Order issues, timing, friendliness,Cleanliness.And UITextField is shift below it
I have implemented following code
#pragma mark - Btn Action on start click
- (IBAction)Btn_FirstHorrific:(id)sender {
[self ReviewHorrific];
[self NumOfStarWorstCase];
str_deliveryBoyRating=#"1";
str_customerComment=#"Horrific";
}
- (IBAction)Btn_SecondNah:(id)sender {
[self ReviewSecondNah];
[self NumOfStarOthercase];
str_deliveryBoyRating=#"2";
str_customerComment=#"nah!";
}
- (IBAction)Btn_ThirdItsOk:(id)sender {
[self ReviewItsOk];
[self NumOfStarOthercase];
str_deliveryBoyRating=#"3";
str_customerComment=#"Its ok";
}
- (IBAction)Btn_FourthGood:(id)sender {
[self ReviewGood];
[self NumOfStarOthercase];
str_deliveryBoyRating=#"4";
str_customerComment=#"good";
}
- (IBAction)Btn_FifthAmazing:(id)sender {
[self ReviewAmazing];
[self NumOfStarOthercase];
str_deliveryBoyRating=#"5";
str_customerComment=#"Amazing";
}
#pragma mark - Change star colour in Number of star changes
- (void)ReviewHorrific{
Btn_FirstHorrific.tintColor = UIColorFromRGB(0xff8133);
Btn_SecondNah.tintColor = [UIColor whiteColor];
Btn_ThirdItsOk.tintColor = [UIColor whiteColor];
Btn_FourthGood.tintColor = [UIColor whiteColor];
Btn_FifthAmazing.tintColor = [UIColor whiteColor];
lbl_report.text=#"Please report your issue";
lbl_RateType.text=#"Horrific";
self.View_WorstCase.hidden = FALSE;
}
- (void)ReviewSecondNah{
Btn_FirstHorrific.tintColor = UIColorFromRGB(0xff8133);
Btn_SecondNah.tintColor = UIColorFromRGB(0xff8133);
Btn_ThirdItsOk.tintColor = [UIColor whiteColor];
Btn_FourthGood.tintColor = [UIColor whiteColor];
Btn_FifthAmazing.tintColor = [UIColor whiteColor];
lbl_report.text=#"Please report your issue";
lbl_RateType.text=#"Nah!!";
}
- (void)ReviewItsOk{
Btn_FirstHorrific.tintColor = UIColorFromRGB(0xff8133);
Btn_SecondNah.tintColor = UIColorFromRGB(0xff8133);
Btn_ThirdItsOk.tintColor = UIColorFromRGB(0xff8133);
Btn_FourthGood.tintColor = [UIColor whiteColor];
Btn_FifthAmazing.tintColor = [UIColor whiteColor];
lbl_report.text=#"Please report your issue";
lbl_RateType.text=#"It's OK";
}
- (void)ReviewGood{
Btn_FirstHorrific.tintColor = UIColorFromRGB(0xff8133);
Btn_SecondNah.tintColor = UIColorFromRGB(0xff8133);
Btn_ThirdItsOk.tintColor = UIColorFromRGB(0xff8133);
Btn_FourthGood.tintColor = UIColorFromRGB(0xff8133);
Btn_FifthAmazing.tintColor = [UIColor whiteColor];
lbl_report.text=#"Heap praise if you would like";
lbl_RateType.text=#"Good";
}
- (void)ReviewAmazing{
Btn_FirstHorrific.tintColor = UIColorFromRGB(0xff8133);
Btn_SecondNah.tintColor = UIColorFromRGB(0xff8133);
Btn_ThirdItsOk.tintColor = UIColorFromRGB(0xff8133);
Btn_FourthGood.tintColor = UIColorFromRGB(0xff8133);
Btn_FifthAmazing.tintColor = UIColorFromRGB(0xff8133);
lbl_report.text=#"Glad to hear it. Any comments or feedback?";
lbl_RateType.text=#"Amazing";
}
Step 1)
Add 5 UIButton to your UI file. Then in your header (.h) code, declare the UIButton like so:
IBOutlet UIButton *starOne;
IBOutlet UIButton *starTwo;
IBOutlet UIButton *starThree;
IBOutlet UIButton *starFour;
IBOutlet UIButton *starFive;
Then back in your UI file, link the star button views to your code. Then add the default (non-selected) star images to your buttons (just drag and drop to do this).
Step 2)
Back in your header code, add 5 IBAction methods. These will detect when the star buttons are pressed:
-(IBAction)press_1;
-(IBAction)press_2;
-(IBAction)press_3;
-(IBAction)press_4;
-(IBAction)press_5;
Then add a method as well. This method will handle the star images.
-(void)set_stars:(int)num :(NSString *)desc
Then declare in integer in your header file. This will tell you what the rating is, like so:
int rating;
Also declare an array (this will contain pointers to your star buttons):
NSArray *_starButtons;
Lastly, declare a UILabel to show the name for each rating (and like it to your UI), like so:
IBOutlet UILabel *rating_name;
Step 3)
In your implementation (.m) code, add in the following:
-(IBAction)press_1 {
[self set_stars:1 :#"Horrific"];
}
-(IBAction)press_2 {
[self set_stars:2 :#"nah!"];
}
-(IBAction)press_3 {
[self set_stars:3 :#"Its ok"];
}
-(IBAction)press_4 {
[self set_stars:4 :#"good"];
}
-(IBAction)press_5 {
[self set_stars:5 :#"Amazing"];
}
-(void)set_stars:(int)num :(NSString *)desc {
rating_name.text = [NSString stringWithFormat:#"%#", desc];
for (int loop = 0; loop < 5; loop++) {
if ((loop + 1) <= num) {
[((UIButton*)_starButtons[loop]) setBackgroundImage:[UIImage imageNamed:#"star_ON.png"] forState:UIControlStateNormal];
}
else {
[((UIButton*)_starButtons[loop]) setBackgroundImage:[UIImage imageNamed:#"star_OFF.png"] forState:UIControlStateNormal];
}
}
rating = num;
}
Finally, dont forget to populate the array with your buttons in the viewDidLoad method like so:
_starButtons = #[starOne, starTwo, starThree, starFour, starFive];
I'm trying to change the text in a SKLabelNode at runtime but it crashes the app with an error: CRASH: -[SKLabelNode label]: unrecognized selector sent to instance
I'm calling it from a selectNodeForTouch:(CGPoint)touchlocation method as follows:
if ([[node name]isEqualToString:#"e"]) {
// add current riddle to favourites and change the icon of the star
button *btn = (button *)[self nodeAtPoint:touchLocation];
btn.label.text = #"d";
[(GameViewController *)self.view.window.rootViewController addToFavourites:_currentTomhais];
NSLog(#"Favourited");
}
The button object has the following interface:
#interface button : SKSpriteNode
#property (nonatomic, retain) SKLabelNode *label;
And is initialised as followed in the button.m file
#implementation button
-(instancetype) initWithString:(NSString *)character fontNamed:(NSString *)font size:(float)size{
self = [super init];
if (self) {
[self setSize:CGSizeMake(size, size)];
//icon Text
_label = [[SKLabelNode alloc] initWithFontNamed:font];
_label.name = character;
_label.fontSize = size;
_label.fontColor = [UIColor colorWithRed:150.0f/255.0f
green:166.0f/255.0f
blue:173.0f/255.0f
alpha:1];
[_label setText:character];
_label.position = CGPointMake(0, 0);
[self addChild:_label];
}
return self;
}
Any idea how to change the text on this item at runtime without crashing the app?
You are sending the selector "label" to an SKLabelNode, which doesn't recognize it. The touched node is actually an SkLabelNode, and so you are sending "label" to an SkLabelNode when you are trying to set the text at btn.label.text = #"d";
I'm drawing three rectangles in order to show the loading, however I want to input Alphabets in those rectangles, how can I put letters in that.
My Function:
- (void)configUI {
self.backgroundColor = [UIColor clearColor];
UIView *rect1 = [self drawRectAtPosition:CGPointMake(0, 0)];
UIView *rect2 = [self drawRectAtPosition:CGPointMake(20, 0)];
UIView *rect3 = [self drawRectAtPosition:CGPointMake(40, 0)];
[self addSubview:rect1];
[self addSubview:rect2];
[self addSubview:rect3];
[self doAnimateCycleWithRects:#[rect1, rect2, rect3]];
}
I want to insert the letter "A" in rect1, "B" in rect2 and "C" in rect3.
Use UILabel instead of UIView. Set the label text. (Note that a UILabel has a background color just like a UIView.)
To draw a string on view, you need to create a subclass of UIView. Import this view in your view controller and create above views as object of custom view.
In custom view there is a view override method -
- (void)drawRect:(CGRect)rect;
This is the place where you can draw string and set attributes for drawing.
For example: Custom view class
CustomView.h
#import <UIKit/UIKit.h>
#interface CustomView : UIView
#property (nonatomic, strong) NSString *drawString;
#end
CustomView.m
#import "CustomView.h"
#implementation CustomView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
- (void)drawRect:(CGRect)rect {
NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
textStyle.lineBreakMode = NSLineBreakByClipping;
textStyle.alignment = NSTextAlignmentCenter;
NSDictionary *attributes = #{
NSParagraphStyleAttributeName: textStyle,
// Text font
NSFontAttributeName : [UIFont fontWithName:#"HelveticaNeue" size:20.0],
// Text color
NSForegroundColorAttributeName : [UIColor orangeColor]
};
[self.drawString drawInRect:rect withAttributes:attributes];
}
#end
Now in your code create view object type of this custom class:
- (void)configUI {
self.backgroundColor = [UIColor clearColor];
CustomView *rect1 = [self drawRectAtPosition:CGPointMake(0, 0)];
CustomView *rect2 = [self drawRectAtPosition:CGPointMake(20, 0)];
CustomView *rect3 = [self drawRectAtPosition:CGPointMake(40, 0)];
// This will draw text to view
[rect1 setDrawString:#"A"];
[rect2 setDrawString:#"B"];
[rect3 setDrawString:#"C"];
[rect1 setBackgroundColor:[UIColor whiteColor]];
[rect2 setBackgroundColor:[UIColor whiteColor]];
[rect3 setBackgroundColor:[UIColor whiteColor]];
[self addSubview:rect1];
[self addSubview:rect2];
[self addSubview:rect3];
[self doAnimateCycleWithRects:#[rect1, rect2, rect3]];
}
I would like to intercept a touch on a UITextField, for instance when I first load it I give it a #selector() to load a different method instead of the delegate stuff?
This is my attempt:
descriptionText = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 25.0, infoView.frame.size.width - 20, 100.0)];
descriptionText.backgroundColor = [UIColor whiteColor];
descriptionText.textColor = [UIColor blackColor];
descriptionText.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
descriptionText.userInteractionEnabled = YES;
[descriptionText addTarget:self action:#selector(loadInfoView:) forControlEvents:UIControlEventTouchUpInside];
descriptionText.font = [UIFont fontWithName:#"Helvetica" size:15];
// show view
[infoView addSubview:descriptionText];
However when I debug the method:
- (void)loadInfoView
{
NSLog(#"load other view here");
}
Your problem is in the forControlEvents:: try UIControlEventEditingDidBegin
[descriptionText addTarget:self action:#selector(loadInfoView:) UIControlEventEditingDidBegin];
Your #selector(loadInfoView:) is also wrong if you have - (void)loadInfoView
or #selector(loadInfoView:) and - (void)loadInfoView: (id) sender
or #selector(loadInfoView) and - (void)loadInfoView
However, why you don't use the UITextFieldDelegate?
.m
#interface ViewController () <UITextFieldDelegate>
#property (strong, nonatomic) UITextField *descriptionText;
#end
Remember to:
self.descriptionText.delegate = self;
Then:
-(void) textFieldDidBeginEditing:(UITextField *)textField
{
if (textField == self.descriptionText)
{
[self loadInfoView];
}
}
Keyboard:
If you don't want to show the keyboard you need to add a [descriptionText resignFirstResponder];
I'm not sure you can get actions to be called on a text field on touch like you want.
If that doesn't work, why don't you attach a tap gesture recognizer to your text field?