你的第一个iOS应用(五) 实现视图控制器

来源:互联网 发布:守望先锋好玩吗 知乎 编辑:程序博客网 时间:2024/05/16 00:49

实现视图控制器

下面将通过这几个步骤去实现视图控制器: 你需要添加一个用户名字的属性(property), 实现changeGreeting:函数, 并且确保当用户触控键盘的Done键时,可以让键盘消失.

添加一个用户名字的属性(Property)

你需要添加一个字符串的属性(property)声明来保存用户的名字, 以便你的代码总是可以引用到它. 因此这个属性应该是public的—因为对于代理者(clients)和子类必须要可视—你添加这个声明到视图控制器的头文件中, 也就是HelloWorldViewController.h文件. Public属性(Public Property)指示了在你的类中打算如何使用这个对象.

一个属性声明是一个指令,它告诉编译器如何去生成一个变量的存取器函数(accessor methods), 例如变量用来存储用户的名字. (你将会在添加完属性声明后学习到更多关于存取器函数的知识.)

通过这个教程, 目前为止,你不需要去进一步的更改故事板文件. 要想给你自己腾出更多的空间添加之后几步中的代码的话, 那么就再一次点击实用工具视图按钮来隐藏实用工具区域 (或者 通过选择菜单 View > Utilities > Hide Utilities).

bullet
去添加一个用户名字的属性声明 . . .
  1. 在工程导航器中,选择HelloWorldViewController.h文件.

  2. @end语句之前, 给字符串添加一个@property语句.

    这个属性声明应该看起来像这样:

    @property (copy, nonatomic) NSString *userName;

    你可以复制并粘贴上面的代码或者你可以自己在编辑器面板中输入这些代码. 如果你要自己输入这些代码, 在输入的时候,会弹出一个Xcode的提示框,给你作出一些建议来完成你所输入的代码. 例如, 在你开始输入@prop...的时候, Xcode会建议你想要输入的是@property, 于是会在一个行内建议面板(inline suggestion panel)上显示这个@property符号,也就是像下图所示的这样:

    image: ../Art/inline_suggestion.png

    如果你觉得这个建议是合适的 (就像上图所显示的例子那样), 就可以按Return(回车)键来应用这个建议.

    在你继续输入代码的时候, Xcode也许会给你提供一个建议的列表供你选择. 例如,在你输入NSStr...的时候,Xcode也许会显示如下的补全列表:

    image: ../Art/completion_list.png

    当Xcode显示一个补全列表(completion list)的时候,按回车键就可以选择高亮的建议. 如果当前高亮选择的建议不正确 (就像上图所显示的,本来应该写NSString ,却提示NSStream), 那么你可以通过通过方向键来在列表中选择一个合适的.

编译器会自动将你任何声明的属性合并存取器函数(synthesizes accessor methods). 一个存取器函数 是获取或者设置一个对象属性值的函数 (有的时候,存取器函数也被称为 “getters”和"setters"). 例如,编译器自动生成你刚才声明的userName属性的getter与setter的声明, 以及他们的实现:

  • - (NSString *)userName;

  • - (void)setUserName:(NSString *)newUserName;

编译器还会自动去声明私有实例变量去备份每一个已声明的属性.例如, 编译器声明一个名叫_userName的实例变量来备份userName属性

注意: 编译器会将存取器函数生成到已编译的代码中; 它并不将这些函数加入到你的代码中.

实现 changeGreeting: 函数

在前一章的 "配置视图"中, 你配置了Hello按钮,可以在用户触控它的时候,发送一个changeGreeting:消息到视图控制器中.作为这个消息的响应, 你想 视图控制区让标签显示用户在文本框输入的文本. Specifically,  method should那么changeGreeting:函数应该去:

  • 从文本框获取字符串 并且 设置视图控制器的userName属性为这个获取到的字符串.

  • 基于userName属性创建一个新的字符串,并且显示到标签中.

bullet
去实现changeGreeting: 函数. . .
  1. 如果有必要,在工程导航器中选择HelloWorldViewController.m文件.

    当你在实现文件中,将滚动条滚动到文件的末尾,可能会看到Xcode为你添加的空实现函数changeGreeting:

  2. 通过添加如下代码来,完成这个changeGreeting:这个空实现函数:

    - (IBAction)changeGreeting:(id)sender {
     
        self.userName = self.textField.text;
     
        NSString *nameString = self.userName;
        if ([nameString length] == 0) {
            nameString = @"World";
        }
        NSString *greeting = [[NSString alloc] initWithFormat:@"Hello, %@!", nameString];
        self.label.text = greeting;
    }

method这里有几件有趣的事要在changeGreeting:函数中注意下:

  • self.userName = self.textField.text; 从文本框获取文本并且设置文本到视图控制器的userName属性.

    在这个教程中,你实际上不会在其他地方使用到这个保存着用户名的字符串, 但是重要的是要明白它的作用: 它是一个视图控制器所管理的非常简单的模型数据.通常,控制器应该在它自己的模型数据中保存关于应用数据的信息-应用数据不应该存储在用户界面元素中,例如HelloWorld应用的文本框.

  • NSString *nameString = self.userName; 创建一个新的变量 (NSString类型) 并且设置它的值为视图控制器中的userName属性.

  • @"World" 是一个NSString类型的实例, 它表示一个字符串常量. 如果用户运行你的应用但没有输入任何的文本 (那么, [nameString length] == 0),nameString 将会被赋值为 “World”.

  • initWithFormat: 函数是基础框架基础框架提供给你的. 它通过你所指定的格式化字符串来创建一个指定格式的字符串(和ANSI C库中的printf函数很像).

    在格式化字符串的时候, %@表示一个代表字符串对象的占位符 . 而其他在这个双引号之内的字符将会原样显示出来(其他格式控制除外如%lu %lf等).

设置视图控制器为文本框的代理

如果你编译并运行应用, 当你点击按钮的时候你应该会发现,标签显示“Hello, World!”,如果你选择文本框并且可以开始在键盘上输入,但是你应该发现当你完成输入的时候,依然没有办法让键盘消失.

在一个iOS应用中, 当一个允许文本输入的元素成为第一响应者的时候,键盘就会自动显示.; 当这个元素失去第一响应者这个状态的时候,键盘会自动消失. (回忆一下,第一响应者是一个可以第一个获取到一系列事件的通知的对象,例如触控文本框以弹出键盘.) 虽然在你的应用中,没有方法可以直接发送一个消息给键盘,但是你可以通过改变文本输入UI元素的第一响应者状态来让键盘显示或消失.

UITextFieldDelegate协议是定义在UIKit框架中的, 并且它包含textFieldShouldReturn:函数, 当用户触控键盘的Return键时,文本框就会调用这个函数.(不管键盘的这个按钮的标题是什么). 因为你设置了视图控制器来作为文本框的代理 (in “To set the text field’s delegate”), 你可以实现这个函数通过发送 resignFirstResponder来强制让文本框失去第一响应者的状态—通过这种方法就可以让键盘消失了.

注意: 一个协议基本上知识一个函数的列表. 如果一个类遵照(或者说 采取)一个协议, 那么这个类要保证实现这个协议中必须要实现的方法. (协议页可以包含可选方法.)  一个代理协议制订了一个对象可能会给它的代理发送所有的消息.

bullet
去设置HelloWorldViewController作为文本框的代理 . . .
  1. 如果有必要,在工程导航器中选择HelloWorldViewController.m文件.

  2. 实现textFieldShouldReturn函数.

    这个函数应该去告诉文本框放弃第一响应者的状态. 实现如下所示:

    - (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
        if (theTextField == self.textField) {
            [theTextField resignFirstResponder];
        }
        return YES;
    }

    在这个应用中,没有必要去测试theTextField == self.textField这个表达式,因为只有一个文本框. 这是一个很好的使用模式, 但是当你超过了一个相同类型的对象的时候,你也许就得需要区分他们了..

  3. 在工程选择器中,选择HelloWorldViewController.h文件.

  4.  在 @interface这一行的最后, 加上<UITextFieldDelegate>

    你的接口声明应该会是这样:

    @interface HelloWorldViewController : UIViewController <UITextFieldDelegate>
    ...

    这个声明了表示了你得HelloWorldViewController 类要采用UITextFieldDelegate协议.

测试应用

编译并运行应用. 这一次一切应该都像你所期待的那样了. 再模拟器中,你输入完名字后,点击Done按钮则会让键盘消失掉, 然后点击Hello按钮则会在标签上显示 “Hello, 你的名字!”.

你如果应用的行为没有像你所期待的那样, 你需要去寻找错误. 对于一些可能出错的地方, 请参阅 “排除错误和检查代码”.

概括

现在你已经完成了视图控制器的实现,你已经完成了你的第一个iOS应用. 祝贺你!

现在可以返回今天开始学习iOS开发来继续学习iOS开发了.

原创粉丝点击