在iOS中显示文本内容 <- iOS文本编程指南

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在iOS中显示文本内容 <- iOS文本编程指南相关的知识,希望对你有一定的参考价值。

参考技术A

ios中的文本系统在保持易用性的同时提供大量强大的功能。UIKit框架包括了多个高级类来管理文本的显示和输入。UIKit还包括了用于显示html、CSS、以及基于javascript的web内容的类。

文本对象在一定范围的字体、样式、和尺寸中,显示样式化、格式化的文本。UIKit框架提供三种主要的类来在app的用户界面中显示文本内容:

尽管这些类确实能支持显示任意数量的文本,但是标签和文本字段还是经常被用于显示相关的少量文本,通常是一个单独行。另一方面,文本视图用来显示大量的文本。

文本视图对象,由UITextView类创建,显示格式化为段落、列、以及页的文本,具有精细排版的所有特征,例如字距、连字、复杂的换行、以及对齐。这些排版服务通过被称为Text Kit的底层技术(一种强大的布局引擎,易用且可扩展)提供给UITextView。更多关于Text Kit的信息,参见“使用Text Kit来绘制和管理文本”。

图1-1 显示了一个在屏幕上显示主要文本对象的例子。左图显示多种不同的文本字段样式,右图显示一个单独的文本视图。显示在背景上的是镶嵌在表单元格中的UILabel对象,用于显示不同视图。

图 1-1 在UICatalog应用中的文本类

当使用可编辑的文本字段和文本视图时,你应该始终提供委托对象来管理编辑会话。文本视图发送多中不同的通知给委托,以便让它们知道编辑何时开始、何时结束、以及给它们一个机会来重写一些编辑行为。例如,委托可以判断当前文本是否包含有效值,如果没有,组织编辑会话结束。当编辑最终结束时,你还可以使用委托来得到文本值结果,并更新应用的数据模型。

因为在用途上细微差别,所以每个文本视图的委托方法也有细微差别。支持UITextField类的位委托实现UITextFieldDelegate协议的方法。类似的,支持UITextView类的委托实现UITextViewDelegate协议的方法。两种情况下,你并不一定要实现任何协议方法,但是,如果你不实现,文本字段或视图没有什么用处。

“管理文本字段和文本视图”描述了文本字段和文本视图的委托消息的顺序,并讨论了通过这些对象的委托方法执行的个中任务。更多关于UITextFieldDelegate和UITextViewDelegate协议方法的消息,参见UITextFieldDelegate Protocol Reference 和 UITextViewDelegate Protocol Reference。

一个web视图对象显示基于web的内容。它是WKWebView的实例,它允许你将基本上是小型浏览器整合到app的用户界面中。WKWebView类充分利用了和iOS中的Safari中一样的技术,包括完全支持HTML、CSS、以及JavaScript内容。该类还支持很多用户熟知的Safari的内置手势。例如。你可以双击和捏合来缩放页面,以及你可以通过用手指拖拽来滚动页面。

除了显示内容,你还可以使用web 视图对象通过使用web表单收集用户的输入。就像其他UIKit中的文本类一样,如果你在web页面上的表单中有一个可编辑的文本字段,点击该字段就会出现键盘,以便用户可以输入文本。因为这是wb体验的组成部分,web视图自身来管理键盘的显示和关闭。

一个web视图通过它的适当的委托对象,来提供关于页面合适加载、以及是否有加载错误的信息。Web委托是实现一个或多个WKUIDelegate或WKNavigationDelegate协议的方法的对象。你的这些委托方法的实现,可以响应故障,或者执行其他与web页面加载有关的任务。

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

技术分享

  • UIResponder

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

  1.   UIView
  2.   UIViewController
  3.       UIApplication 

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

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

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

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

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

  • 设置 UITextField 的键盘

  UITextField 对象有一系列属性,用于设置弹出的键盘。下面就修改这些属性,为 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。

技术分享

  但是,如果我们点击 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

 

以上是关于在iOS中显示文本内容 <- iOS文本编程指南的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在ios标签中显示html格式的文本

为 iOS 应用返回带有丰富标记的文本

以编程方式在 ios 中的 iMessage 中发送图片+文本?

Sencha Touch:如何以编程方式关注 ios 上的文本字段?

如何在ios中限制UITextView中的内容