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

  • 文本框(UITextField)

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

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

#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 对象。点击文本框,这时屏幕底部就会弹出键盘,用于向文本框中输入文字,下面咱们介绍一下第一响应者。设计模式

  • UIResponder

  UIResponder 是 UIKit 框架中的一个抽象类。以前咱们了解过他的几个子类。api

  1.   UIView
  2.   UIViewController
  3.       UIApplication 

  UIResponder 定义了一系列方法,用于接收和处理用户事件,例如 触摸事件、运动事件(摇晃设备)和功能控制事件(如编辑文本或者音乐播放)等。 UIResponder 的子类会覆盖这些方法,实现本身的事件响应代码。安全

  在以上事件中,触摸事件显然应该由被触摸的视图负责处理。系统会将触摸事件直接发送给被触摸的视图。session

  其余类型的事件则会由第一响应者负责处理,UIWindow 有一个  firstResponder 属性指向第一响应者。例如,当用户点击 UITextField 对象时, UITextField 对象就会成为第一响应者。UIWindow 会将  firstResponder 指向该对象,以后,若是应用接收到运动事件和功能控制事件,都会发送给 UITextField 对象。app

  当某个 UITextField 对象或 UITextView 对象成为第一响应者时,屏幕就会弹出键盘。除了用户点击以外,还能够在代码中向 UITextField 对象发送 becomeFirstResponder 消息,使其成为第一响应者。相反,若是要关闭键盘,则能够向 UITextField 对象发送  resignFirstResponder 消息,且要求改对象放弃第一响应者状态。一旦第一响应者不是 UITextField 对象,键盘就会消失。框架

  实际上,大部分视图都不须要成为第一响应者。例如 UISlider 对象,该对象只会处理触摸事件(用户拖拽滑块),而不会接收其余类型的事件,所以它不须要成为第一响应者。dom

  • 设置 UITextField 的键盘

  UITextField 对象有一系列属性,用于设置弹出的键盘。下面就修改这些属性,为 UITextField 对象添加占位符文本,并修改键盘的换行键盘类型。ide

#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。

  可是,若是咱们点击 Done 就会发现没有任何反应。实际上,修改换行键盘的类型知识改变了换行键的外观,若是须要实现用户点击换行键后的功能,必须实现编写响应的代码。在编写代码以前,在介绍 UITextField 对象中另外介个有用的属性

autocapitalizatioType

设置 UITextField 对象的自动大写功能,

包括 none(关闭自动大写)功能、words(单词)、sentences(句子)、allcharacters(全部字母)四种类型

autocorrectionType

启用/禁用(设置为YES/NO,下同)UITextField 对象的拼写建议功能,

能够提示用户输错的单词并提供修改建议

endblesReturnKeyAutomatically

启用/禁用 UITextField 对象的换行键自动检测功能。

若是将该属性设置为 YES ,UITextField 对象会自动监测用户输入,并根据是否输入了文字 启用/禁用 换行键。

keyboardType

设置 UITextField 对象弹出的键盘类型,

例如 ASCII 、 Capable(ASCII标准键盘)、 E-mail Address(电子邮件地址)Number Pad(数字键盘) 和 URL(网址)

secureTextEntry

启用/禁用 UITextField 对象的安全输入功能,

若是将该属性设置为 YES,UITextField 对象会以圆点代替用户输入的文字,相似于一般见到的密码文本框

  • 委托

  咱们知道 目标-动做(Target-Action)设计模式。目标-动做 是 UIKit 中一般用的设计模式之一。目标-动做的工做方式为:当某个特定的事件发生时(例如按下按钮),发生事件的一方会向指定的目标对象发送一个以前设定好的动做消息。全部继承 UIControl 对象均可以设置目标-动做。

  在 目标-动做中,针对不一样的事件,须要建立不一样的动做消息。UIButton 对象的事件比较简单,一般只须要处理点击事件:相反,像 UITextField 这类事件复杂的对象,伟大的苹果使用了 委托设计模式 。UITextField 对象具备一个委托属性,经过为 UITextField 对象设置委托,UITextField 对象会在发生事件时向委托发送响应的消息,由委托处理该时间。例如,对于编辑 UITextField 对象文本内容的事件,有对象的委托方法。

@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

  构建并运行。

 

  • 运动效果

  iOS设备内嵌了许多功能强大的传感器,例如加速传感器,磁场传感器和三轴陀螺仪等。应用能够经过这些传感器了解设备加速,方向和角度,并实现有用的功能。例如,应用能够根据设备的方向自动将界面调整为横屏或者竖屏模式。从iOS7开始,苹果引用了一些新 API 能够轻松为应用添加一种经过传感器实现的视觉差效果。

  咱们能够想象本身坐在一辆飞驰的大奔中,咱们看想窗外,会发现远处的景物的倒退速度比近处的慢不少。这是大脑对空间和速度差别产生的一种错觉,称之为视差。在iOS7 及以后这种效果随处可见,例如,在主屏幕中,若是稍微倾斜设备,能够发现主屏幕中的图标会随着倾斜方向相对于壁纸移动。

  应用能够经过  UIInterpolatingMotionEffect 类来实现相同的效果,咱们只须要建立一个  UIInterpolatingMotionEffect 对象,设置其方向(垂直或者水平)、键路劲(key path,须要使用视差效果的属性)和相对最小/最大值(视觉差的范围),再将其添加到某个视图上,该视图就能得到相应的视差效果。

#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
相关文章
相关标签/搜索