沃梦达 / IT编程 / 移动开发 / 正文

iOS 委托与文本输入(内容根据iOS编程编写)

这篇文章主要介绍了iOS 委托与文本输入(内容根据iOS编程编写) 的相关资料,需要的朋友可以参考下

•文本框(UITextField)

  本章节继续编辑 JXHypnoNerd 。文件地址 。

  首先我们继续编辑 JXHypnosisViewController.m 修改 loadView 方法,向 view 中添加一个 UITextField 对象:


#import "JXHypnosisViewController.h"
#import "JXHypnosisView.h"
@interface JXHypnosisViewController ()
@end
@implementation JXHypnosisViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// 设置标签项的标题
self.tabBarItem.title = @"Hypnotize";
// 从图片文件创建一个 UIImage 对象
UIImage * i = [UIImage imageNamed:@"Hypno"];
// 将 UIImage 对象赋值给标签项的 iamge 属性
self.tabBarItem.image = i;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)loadView {
// 创建一个 JXHypnosisView 对象
JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init];
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField * textField = [[UITextField alloc] init];
textField.frame = textFieldRect;
// 设置 UITextField 对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
[backgroundView addSubview:textField];
// 将 JXHypnosisView 对象赋给视图控制器的view 属性
self.view = backgroundView;
}
@end

  构建并运行应用,项目中会显示一个文本框,该文本框就是刚才我们添加的 UITextField 对象。点击文本框,这时屏幕底部就会弹出键盘,用于向文本框中输入文字,下面我们介绍一下第一响应者。


#import "JXHypnosisViewController.h"
#import "JXHypnosisView.h"
@interface JXHypnosisViewController ()
@end
@implementation JXHypnosisViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// 设置标签项的标题
self.tabBarItem.title = @"Hypnotize";
// 从图片文件创建一个 UIImage 对象
UIImage * i = [UIImage imageNamed:@"Hypno"];
// 将 UIImage 对象赋值给标签项的 iamge 属性
self.tabBarItem.image = i;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)loadView {
// 创建一个 JXHypnosisView 对象
JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init];
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField * textField = [[UITextField alloc] init];
textField.frame = textFieldRect;
// 设置 UITextField 对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
// 修改占位符
textField.placeholder = @"Hypontize me";
// 修改键盘类型
textField.returnKeyType = UIReturnKeyDone;
[backgroundView addSubview:textField];
// 将 JXHypnosisView 对象赋给视图控制器的view 属性
self.view = backgroundView;
}
@end

  构建并运行,在程序中就会发现有一行占位符文本 Hypontize me ,当用户在程序中输入文字的时候,占位文本就会消失。换行键不再显示默认的 Return,而是 Done。


@protocol UITextFieldDelegate <NSObject>
@optional
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; // return NO to disallow editing.
- (void)textFieldDidBeginEditing:(UITextField *)textField; // became first responder
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField; // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
- (void)textFieldDidEndEditing:(UITextField *)textField; // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; // return NO to not change text
- (BOOL)textFieldShouldClear:(UITextField *)textField; // called when clear button pressed. return NO to ignore (no notifications)
- (BOOL)textFieldShouldReturn:(UITextField *)textField; // called when 'return' key pressed. return NO to ignore.
@end

  注意:在委托方法中,通常应该将对象自身作为第一个参数。多个对象可能具有相同的委托,当委托收到消息的时候,需要根据该参数判断发送该消息的对象。例如,如果某个视图控制器中包含多个 UITextField 对象,它们的委托都是该视图控制器,那么视图控制器就需要根据 textField 参数获取响应的 UITextField 对象并执行不同的操作。

  下面我们就将 UITextField 对象所位于的视图控制器- JXHypnosisViewController 设置为它的委托,并实现 textFieldShouldReturn: 委托方法,当用户点击 Done 按钮时,UITextField 对象就会调用该方法。

  打开 JXHypnosisViewController 修改 loadView 方法,将 UITextField 对象的委托属性设置为 JXHypnosisViewController 自身。

   textFieldShouldReturn: 只有一个参数,就是用户点击换行键的相应 UITextField 对象。目前,应用只会向控制台输出 UITextField 对象的文本内容。

  接下来在代码中实现 textFieldShouldReturn: 方法。


#import "JXHypnosisViewController.h"
#import "JXHypnosisView.h"
@interface JXHypnosisViewController ()
@end
@implementation JXHypnosisViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// 设置标签项的标题
self.tabBarItem.title = @"Hypnotize";
// 从图片文件创建一个 UIImage 对象
UIImage * i = [UIImage imageNamed:@"Hypno"];
// 将 UIImage 对象赋值给标签项的 iamge 属性
self.tabBarItem.image = i;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)loadView {
// 创建一个 JXHypnosisView 对象
JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init];
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField * textField = [[UITextField alloc] init];
textField.frame = textFieldRect;
// 设置 UITextField 对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
// 修改占位符
textField.placeholder = @"Hypontize me";
// 修改键盘类型
textField.returnKeyType = UIReturnKeyDone;
textField.delegate = self;
[backgroundView addSubview:textField];
// 将 JXHypnosisView 对象赋给视图控制器的view 属性
self.view = backgroundView;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(@"%@",textField.text);
return YES;
}
@end

  构建并运行程序,就可以在控制台打印信息,但是这里会有一处警告,暂时先不管。

  请注意, JXHypnosisViewController 不需要实现 UITextField 对象的所有委托方法,UITextField 对象会在运行时检查委托方法是否实现了某个方法,如果没有实现 UITextField 对象就不会调用该方法。

•协议

  凡是支持委托的对象,其背后都有一个相应的协议,声明可以向该对象(例如:UITextField)的委托对象(例如:JXHypnosisViewController)发送的消息。委托对象(例如:JXHypnosisViewController)需要根据这个协议为其响应的事件实现响应的方法。如果一个类实现了某个协议中规定的方法,就称这个类遵守该协议。

  声明协议的语法是,使用 @protocol 指令开头,后跟协议的名称(例如:UITextFieldDelegate)。尖括号里的 NSObject 是指只 NSObject 协议,其作用是声明 UITextFieldDelegate 中包含 NSObject 协议的全部方法。接着声明新协议特有的方法,最后使用 @end 指令来结束。

  协议不是类,只是一组方法声明。不能为协议创建对象,或者添加实例变量。协议自身不实现方法,需要由遵守相应协议的类来实现。

  协议所声明的方法可以是必须的(required)或者是可选的(optional)。协议方法默认都是必须的,所以当我们自定义协议的时候最好设置一下。使用 @optional 指令,可以将写在该指令之后的方法去全部声明为可选的。

  发送方在发送可选方法之前,都会先向其委托发送另一个名为 respondsToSelector: 的消息。所有Objective-C 对象都从 NSObject 继承了 respondsToSelector: 方法,该方法能在运行时检查对象是否实现了指定的方法。 @selector() 指令可以将选择器(selector)转换成数值,以便将其作为参数进行传递。


- (void)clearButtonTapped {
// textFieldShouldClear:是可选方法,需要先检查委托是否实现了该方法
SEL clearSelector = @selector(textFieldShouldClear:);
if ([self.delegate respondsToSelector:clearSelector]) {
self.text = @"";
}
}

  如果某个方法是必须的,那么发送发可以直接向其委托对象发送相应的消息,不用检查委托对象是否实现了该方法。这也就意味着,如果委托对象没有实现相应的方法,应用就会抛出位置选择器(unrecognized selector)异常,导致应用崩溃。

  为了防止问题,编译器会检查某个类是否实现了相关协议的必须方法。要让编译器能够执行此类检查,必须将相应的类声明为遵守指定的协议,其语法格式为:在头文件或类扩展 @interface 指令末尾,将类所遵守的协议以都好分隔的列表形式写在尖括号里。


#import "JXHypnosisViewController.h"
#import "JXHypnosisView.h"
@interface JXHypnosisViewController ()<UITextFieldDelegate>
@end
@implementation JXHypnosisViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// 设置标签项的标题
self.tabBarItem.title = @"Hypnotize";
// 从图片文件创建一个 UIImage 对象
UIImage * i = [UIImage imageNamed:@"Hypno"];
// 将 UIImage 对象赋值给标签项的 iamge 属性
self.tabBarItem.image = i;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)loadView {
// 创建一个 JXHypnosisView 对象
JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init];
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField * textField = [[UITextField alloc] init];
textField.frame = textFieldRect;
// 设置 UITextField 对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
// 修改占位符
textField.placeholder = @"Hypontize me";
// 修改键盘类型
textField.returnKeyType = UIReturnKeyDone;
textField.delegate = self;
[backgroundView addSubview:textField];
// 将 JXHypnosisView 对象赋给视图控制器的view 属性
self.view = backgroundView;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(@"%@",textField.text);
return YES;
}
@end

  几乎所有的委托都是弱引用属性。这是为了避免对象及其委托之间产生强引用循环。例如: JXHypnosisViewController 是 UITextField 对象的委托,而且 UITextField 对象是 JXHypnosisViewController 的强引用属性,如果 UITextField 对象再对其委托保持强引用就会在两者之间产生强引用循环。

•向屏幕中添加UILabel对象

  下面我们在 JXHypnosisViewController 中添加一个新方法,在屏幕中随机位置绘制20个 UILabel 对象。同时,该方法有一个 NSString 类型的参数,表示 UILabel 对象显示的文字。


#import "JXHypnosisViewController.h"
#import "JXHypnosisView.h"
@interface JXHypnosisViewController ()<UITextFieldDelegate>
@end
@implementation JXHypnosisViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// 设置标签项的标题
self.tabBarItem.title = @"Hypnotize";
// 从图片文件创建一个 UIImage 对象
UIImage * i = [UIImage imageNamed:@"Hypno"];
// 将 UIImage 对象赋值给标签项的 iamge 属性
self.tabBarItem.image = i;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)loadView {
// 创建一个 JXHypnosisView 对象
JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init];
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField * textField = [[UITextField alloc] init];
textField.frame = textFieldRect;
// 设置 UITextField 对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
// 修改占位符
textField.placeholder = @"Hypontize me";
// 修改键盘类型
textField.returnKeyType = UIReturnKeyDone;
textField.delegate = self;
[backgroundView addSubview:textField];
// 将 JXHypnosisView 对象赋给视图控制器的view 属性
self.view = backgroundView;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(@"%@",textField.text);
return YES;
}
- (void)drawHypnoticMessage:(NSString *)message {
for (NSInteger i = 0; i < 20; i++) {
UILabel * messageLabel = [[UILabel alloc] init];
// 设置 UIlabel 对象的文字和颜色
messageLabel.backgroundColor = [UIColor clearColor];
messageLabel.textColor = [UIColor whiteColor];
messageLabel.text = message;
//根据要显示的文字调整 UILabel 对象的大小
[messageLabel sizeToFit];
// 获取随机 x 坐标
// 使 UILabe 对象的宽度不超出控制器的 view 宽度
NSInteger width = self.view.bounds.size.width - messageLabel.bounds.size.width;
NSInteger x = arc4random() % width;
// 获取随机 y 坐标
// 使 UILabel 对象的高度不超出控制器的 view 宽度
NSInteger height = self.view.bounds.size.height - messageLabel.bounds.size.height;
NSInteger y = arc4random() % height;
// 设置 UILabel 对象的 frame
CGRect frame = messageLabel.frame;
frame.origin = CGPointMake(x, y);
messageLabel.frame = frame;
// 将 UILabel 对象添加到控制器的 view 中
[self.view addSubview:messageLabel];
}
}
@end

  接下来修改 textFieldShouldReturn: 将 UITextField 对象的文本内容作为 参数,调动我们自定义的方法,之后清空文本内容,最后调用 resignFirstResponder 关闭键盘。


#import "JXHypnosisViewController.h"
#import "JXHypnosisView.h"
@interface JXHypnosisViewController ()<UITextFieldDelegate>
@end
@implementation JXHypnosisViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// 设置标签项的标题
self.tabBarItem.title = @"Hypnotize";
// 从图片文件创建一个 UIImage 对象
UIImage * i = [UIImage imageNamed:@"Hypno"];
// 将 UIImage 对象赋值给标签项的 iamge 属性
self.tabBarItem.image = i;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)loadView {
// 创建一个 JXHypnosisView 对象
JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init];
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField * textField = [[UITextField alloc] init];
textField.frame = textFieldRect;
// 设置 UITextField 对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
// 修改占位符
textField.placeholder = @"Hypontize me";
// 修改键盘类型
textField.returnKeyType = UIReturnKeyDone;
textField.delegate = self;
[backgroundView addSubview:textField];
// 将 JXHypnosisView 对象赋给视图控制器的view 属性
self.view = backgroundView;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(@"%@",textField.text);
[self drawHypnoticMessage:textField.text];
textField.text = @"";
[textField resignFirstResponder];
return YES;
}
- (void)drawHypnoticMessage:(NSString *)message {
for (NSInteger i = 0; i < 20; i++) {
UILabel * messageLabel = [[UILabel alloc] init];
// 设置 UIlabel 对象的文字和颜色
messageLabel.backgroundColor = [UIColor clearColor];
messageLabel.textColor = [UIColor whiteColor];
messageLabel.text = message;
//根据要显示的文字调整 UILabel 对象的大小
[messageLabel sizeToFit];
// 获取随机 x 坐标
// 使 UILabe 对象的宽度不超出控制器的 view 宽度
NSInteger width = self.view.bounds.size.width - messageLabel.bounds.size.width;
NSInteger x = arc4random() % width;
// 获取随机 y 坐标
// 使 UILabel 对象的高度不超出控制器的 view 宽度
NSInteger height = self.view.bounds.size.height - messageLabel.bounds.size.height;
NSInteger y = arc4random() % height;
// 设置 UILabel 对象的 frame
CGRect frame = messageLabel.frame;
frame.origin = CGPointMake(x, y);
messageLabel.frame = frame;
// 将 UILabel 对象添加到控制器的 view 中
[self.view addSubview:messageLabel];
}
}
@end

  构建并运行。


#import "JXHypnosisViewController.h"
#import "JXHypnosisView.h"
@interface JXHypnosisViewController ()<UITextFieldDelegate>
@end
@implementation JXHypnosisViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// 设置标签项的标题
self.tabBarItem.title = @"Hypnotize";
// 从图片文件创建一个 UIImage 对象
UIImage * i = [UIImage imageNamed:@"Hypno"];
// 将 UIImage 对象赋值给标签项的 iamge 属性
self.tabBarItem.image = i;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)loadView {
// 创建一个 JXHypnosisView 对象
JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init];
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField * textField = [[UITextField alloc] init];
textField.frame = textFieldRect;
// 设置 UITextField 对象的边框样式,便于查看它在屏幕上的位置
textField.borderStyle = UITextBorderStyleRoundedRect;
// 修改占位符
textField.placeholder = @"Hypontize me";
// 修改键盘类型
textField.returnKeyType = UIReturnKeyDone;
textField.delegate = self;
[backgroundView addSubview:textField];
// 将 JXHypnosisView 对象赋给视图控制器的view 属性
self.view = backgroundView;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self drawHypnoticMessage:textField.text];
textField.text = @"";
[textField resignFirstResponder];
return YES;
}
- (void)drawHypnoticMessage:(NSString *)message {
for (NSInteger i = 0; i < 20; i++) {
UILabel * messageLabel = [[UILabel alloc] init];
// 设置 UIlabel 对象的文字和颜色
messageLabel.backgroundColor = [UIColor clearColor];
messageLabel.textColor = [UIColor whiteColor];
messageLabel.text = message;
//根据要显示的文字调整 UILabel 对象的大小
[messageLabel sizeToFit];
// 获取随机 x 坐标
// 使 UILabe 对象的宽度不超出控制器的 view 宽度
NSInteger width = self.view.bounds.size.width - messageLabel.bounds.size.width;
NSInteger x = arc4random() % width;
// 获取随机 y 坐标
// 使 UILabel 对象的高度不超出控制器的 view 宽度
NSInteger height = self.view.bounds.size.height - messageLabel.bounds.size.height;
NSInteger y = arc4random() % height;
// 设置 UILabel 对象的 frame
CGRect frame = messageLabel.frame;
frame.origin = CGPointMake(x, y);
messageLabel.frame = frame;
// 将 UILabel 对象添加到控制器的 view 中
[self.view addSubview:messageLabel];
UIInterpolatingMotionEffect * motionEffect;
motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[messageLabel addMotionEffect:motionEffect];
motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[messageLabel addMotionEffect:motionEffect];
}
}
@end

  测试运动效果必须在真机上。

•深入学习:main() 和 UIApplication

  用C语言编写的程序,其至此那个入口都是 main() 。用 Objective-C 语言编写的程序也是这样。

  在 JXHypnoNerd 项目中我们在 mian.m,可以看到有如下代码


#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

  这段代码中的 UIApplicationMain 函数会创建一个 UIApplication 对象。 每个iOS应用都有且只有一个UIApplication对象,该对象的作用就是维护运行循环。一旦程序创建了某个 UIApplication 对象,该对象的运行循环就会一直循环下去,main() 的执行也会因此堵塞。

  此外, UIApplicationMain 函数还会创建某个指定类的对象,并将其设置为 UIApplication 对象的 delegate 。该对象的类是由 UIApplicationMain 函数的最后一个实参指定的,该实参的类型是 NSString 对象,代表的是某个类的类名。所以在以上这段代码中, UIApplicationMain 会创建一个 AppDelegate 对象,并将其设置为 UIApplication 对象的 delegate 。

  在应用启动运行循环并开始接收事件之前,UIApplication 对象会向其委托发送一个特性的消息,使应用能有机会完成相应的初始化工作。这个消息的名称是


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

以上所述是小编给大家介绍的iOS 委托与文本输入(内容根据iOS编程编写),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程学习网网站的支持!

本文标题为:iOS 委托与文本输入(内容根据iOS编程编写)