iOS programming Delegation and Text Input
iOS programming Delegation and Text Input
1.1 Text Fields
CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
UITextField *textField = [[UITextField alloc] initWithFrame:textFieldRect];
// Setting the border style on the text field will allow us to see it more easily textField.borderStyle = UITextBorderStyleRoundedRect;
[backgroundView addSubview:textField];
Tap on the text field, and the keyboard will slide up from the bottom of the screen, allowing you to input text. To understand how this is happening under the hood, you need to understand the first responder.
当你点击text field 时,这个keyboard 将会从屏幕的底部滑上来。要明白在底层发生了什么,你必须明白first responder.
1.2 UIResponder
UIResponder is an abstract class in the UIKit framework. It is the superclass of three classes that you have already encountered:
UIView
UIViewController
UIApplication
UIResponder 是UIKit 框架的一个抽象类。他是以下你看到过的三个类的超类。
UIView
UIViewController
UIApplication
UIResponder defines methods for handling (or "responding to") events: touch events, motion events (like a shake), and remote control events (like pausing or playing).
UIResponder定义了处理 事件,触摸事件,运动事件和远程控制事件的方法。
Subclasses override these methods to customize how they respond to events.
子类重载这些方法来适应他们如何响应事件。
With touch events, it is obvious which view the user has touched. Touch events are sent directly to that view.
触摸事件,很明显用户触摸了哪个事件。触摸事件之间送到那个view。
The UIWindow has a pointer called firstResponder which indicates who should respond to the other types of events.
UIWindow 有一个叫做firstResponse的指针。它指向那个谁应该响应其他类型的事件。
When you select a text field, for example, the window moves its firstResponder pointer to that text field.
如果你选择 text field ,window 将把fristResponse 指向text field。
When a text field or a text view becomes firstResponder, it shows its keyboard. When it loses first responder status, it hides its keyboard.
当一个text field 或text view 成为firstResponse,它将显示键盘。当它不是firstResponse,它将隐藏键盘。
If you want one of these views to become first responder, you send it the message becomeFirstResponder and the keyboard appears. When you want to hide the keyboard, you send it the message resignFirstResponder.
如果你想让这些视图的一个成为first responder ,你应该发送becomeFirstResponder 的消息,键盘就出现了。 当你想隐藏keyboard,你向它发送resignFirstResponder消息。
Most views refuse to become first responder;
很多视图不想成为first responder.
1.3 Configuring the keyword
textField.placeholder = @"Hypnotize me";
textField.returnKeyType = UIReturnKeyDone;
the return key now says Done instead of the default Return.
In fact, the return key does not do anything automatically; you have to implement the return key functionality yourself.
return key 并没有自动的做某事。你必须实现 返回键函数。
some of the other useful properties that you can use to configure the keyboard.
下面是一些有关配置keyboard 的属性。
autocapitalizationType
This determines how capitalization is handled. The options are none, words, sentences, or all characters.
这个决定大写字母如何处理。选项是无,字,句子,和所有字符。
autocorrectionType
This will suggest and correct unknown words. This value can be YES or NO.
这个将会建议和更改未知的词语。这个值可以设置为YES or NO。
enablesReturnKeyAutomatically
This value can be YES or NO. If set to yes, the return key will be disabled if no text has been typed. As soon as any text is entered, the return key becomes enabled.
keyboardType
This determines the type of keyboard that will be displayed. Some examples are the ASCII keyboard, email address keyboard, number pad, and the URL keyboard.
设置键盘是ASCII 还是email键盘,数字键盘还是URL键盘。
secureTextEntry
Setting this to YES makes the text field behave like a password field, hiding the text that is entered.
设置为密码形式的输入
1.4 Delegation
This is one form of callbacks that is used by UIKit: When a button is tapped, it sends its action message to its target. This typically triggers code that you have written.
当一个button 按下后,它发送一个action 消息给目标。这触发了你写过的代买。
You introduce the text field to one of your objects: "This is your delegate, when anything interesting happens in your life, send a message to him."
你把text field 引入你的一个对象: 这是你的委托,当任何感兴趣的事情在你的生命周期发生时,给她发送一个消息。
The text field keeps a pointer to its delegate.
text field 有一个指针指向它的委托。
Many of the message it sends to its delegates are informative: "OK, I am done editing!".
许多发给他的delegate的消息是:好,我已经完成编辑。
- (void)textFieldDidEndEditing:(UITextField *)textField;
- (void)textFieldDidBeginEditing:(UITextField *)textField;
Notice that it always sends itself as the first argument to the delegate method.
注意:它总是把自己作为第一个参数 传递给它的委托方法。
Some of the message it sends to its delegate are queries: "I am about to end editing and hide the keyboard. OK?"
一些传递给它的委托有关询问的消息:我将要结束编辑和隐藏键盘。可以吗
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; - (BOOL)textFieldShouldClear:(UITextField *)textField;
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
textField.delegate = self;
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(@"%@", textField.text);
return YES; }
1.5 protocol
Before sending an optional message, the object first asks its delegate if it is okay to send that message by sending another message, respondsToSelector:.
当发送一个可选择的信息时,object 将通过responseToSelector:询问它的delegate ,看看object向它的delegate是否可以。
- (void)clearButtonTapped
{
// textFieldShouldClear: is an optional method,
// so we check first
SEL clearSelector = @selector(textFieldShouldClear:);
if ([self.delegate respondsToSelector:clearSelector]) { if ([self.delegate textFieldShouldClear:self]) {
self.text = @""; }
} }
If a method in a protocol is required, then the message will be sent without checking first. This means that if the delegate does not implement that method, an unrecognized selector exception will be thrown, and the application will crash.
如果一个method 在protocol 是必须得,那么这个消息不检查就发送。这也就意味着如果你没有实现该方法,那么一个未检查到selector 异常将会抛出。
This is done either in the class header file or the class extension: the protocols that a class conforms to are added to a commadelimited list inside angled brackets in the interface declaration.
@interface BNRHypnosisViewController () <UITextFieldDelegate>
@end
The reason for adding it to the class extension rather than the header file is the same reason as always: add to the class extension if the information (conforming to a particular protocol in this case) does not need to be publicly visible, and add it to the header file if other objects do need to know about the information.
既可以把protocol 添加到class extension 也可以添加到interface 中。
Many classes have a delegate pointer, and it is nearly always a weak reference to prevent strong reference cycles.
许多类都有一个delegate pointer,并且他们都是弱引用以组着强引用循环。
1.6 Adding the Labels to the Screen
To make things a little interesting, you are going to add instances of UILabel to the screen at random positions.
你将在屏幕的随机位置添加UILabel。
arc4random() %4 will generate 0, 1, 2 or 3.
arc4random()%5 将产生0,1,2,3,4
update the textFieldShouldReturn: method to call this new method, passing in the text field's text, clear the text that the user typed, and then dismiss the keyboard by calling resignFirstResponder.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(@"%@", textField.text);
[self drawHypnoticMessage:textField.text];
textField.text = @"";
[textField resignFirstResponder];
return YES; }
1.7 Motion Effects 运动效果
accelerometer, magnetometer, and gyroscope – help determine the orientation of the device.
加速器,磁强计,陀螺仪帮助我们决定设备的方向。
When you drive down the road, the signs along the shoulder appear to move much more quickly than trees in the distance.
当你开车在路上,在路旁的图片要明显的比远处的路标移动的快。
Your brain interprets this difference in apparent speed as movement in space. This visual effect is called "parallax".
你的大脑在移动速度够明显时解析这种不同。 这个虚拟的效果成为parallax(视差)
With iOS 7, you have probably noticed this on the home screen where the icons appear to move relative to the wallpaper when you tilt the device. It is used subtly (and not so subtlety) in various places across the operating system and bundled apps, including the red badges on Home screen icons, the volume changer pop-up, and alert views.
你注意到在home 屏时,当你倾斜屏幕时,图标相对移动。
Applications can access the same technology that powers those effects by using the UIInterpolatingMotionEffect class.
应用程序也可以通过使用UIInterpolatingMotionEffect获得同样地技术。
Instances are given an axis (either horizontal or vertical), a key path (which property of the view do you want to impact), and a relative minimum and maximum value (how much the key path is allowed to sway in either direction).
实例变量将提供一个坐标轴,(水平的或垂直的),一个关键路径(你想影响视图的那个属性)和一个相对最小最大值(在任意方向上,最大最小能摇晃的区间)
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];
1.8 Using breakpoints
This navigator shows a stack trace of where the breakpoint stopped execution
这个导航显示了breakpoint 停止执行的stack trace .
A stack trace shows you the methods and functions whose frames were in the stack when the application broke.
a stack trace 显示了一些方法和函数。这些函数和方法指明了那个框架在栈里,什么时候应用停止的。
The method where the break occurred is at the top of the stack trace.
在哪里停止的方法在stack 的最上面。
Select the method at the top of the stack. In the debug area below the editor area, check out the variables view to the left of the console. This area shows the variables within the scope of BNRHypnosisView's initWithFrame: method along with their current values
选择stack 最上面的方法,在debug area 区域检查左侧的变量。这个区域将展示在initWithFrame的变量的现有值。
1.8 main() and UIApplication
Open main.m in the HypnoNerd project navigator. It looks like this:
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv,
nil, NSStringFromClass([BNRAppDelegate class]));
} }
The function UIApplicationMain creates an instance of a class called UIApplication.
UIApplicationMain 函数 创办了一个成为UIApplication 的实例。
For every application, there is a single UIApplication instance.
对于每个程序来说只有一个UIApplication .
This object is responsible for maintaining the run loop. Once the application object is created, its run loop essentially becomes an infinite loop: the executing thread will never return to main().
一旦UIApplication创建好,它的 run loop 将变成无限循环:执行的线程不会返回到main中。
Another thing the function UIApplicationMain does is create an instance of the class that will serve as the UIApplication's delegate.
UIApplication还创建了作为UIApplication的委托的类的实例。
Notice that the final argument to the UIApplicationMain function is an NSString that is the name of the delegate's class. So, this function will create an instance of BNRAppDelegate and set it as the delegate of the UIApplication object.
注意到UIApplicMain 最后的参数是个字符串。作为delegate 类的名字。
The first event added to the run loop in every application is a special "kick-off" event that triggers the application to send a message to its delegate. This message is application:didFinishLaunchingWithOptions:.
添加到run loop 的第一个事件是特殊的kick-off 事件。它将触发application 发送一个消息给它的代理。这个消息就是application:didFinishLaunchingWithOptions.
You implemented this method in BNRAppDelegate.m to create the window and the controller objects used in this application.
你在BNRAppDelegate.m中实现这个方法来创建窗口和用在application的controller 对象。
Every iOS application follows this pattern.
每个iOS application 都应用了这个模式。