Learn Objective-C: Day 1

欢迎来到令人振奋的Objective-C的世界。通过这一系列的文章,我希望可以让零基础的人可以自信的写出自己的应用。这不是一件可以仓促达成的事情,所以要注重基础部分,不要直接跳过它们。我们不仅直接传授最精华的部分,而且会不断打磨你的代码,直到最好。让我们现在就开始吧!

什么是Objective-C?

如果你正在读这篇文章,我猜想你大概已经知道答案了。如果你不知道也没有关系,因为我会用下面的部分为你仔细解答。

Objectiv-C是一个基于C的面向对象语言。它主要用于编写Mac OS X桌面操作系统及iPhone操作系统(我们现在称之为iOS)。它由NeXTSTEP操作系统发展而来。NeXTSTEP操作系统后来被苹果公司收购,并且演变成了Mac OS X。这就解释了为什么它现在与苹果操作系统如此相像。

因为Objective-C是C语言的一个超集,在Objective-C中C语言可以被完美编译。因为任何Objective-C的编译器可以直接编译C代码,所以Objective-C具有所有C语言的性质。
如果你对这点有些困惑,那么可以这么认为:任何C可以做到的事情,Objective-C也可以做到,反之不成立。

我需要什么?

我们不会关注如何编译iPhone应用,而是更多的把重点放到语言本身上。所以我们需要一台Mac电脑和一个编辑器(如GCC)。如果你已经通过苹果安装了开发者工具(如Xcode,Interface Builder等),那么GCC应该已经被安装了。如果没有的话,请到苹果开发者网站获取。

就先决条件而言,你不需要很强的计算机科学背景,一些C的编程基础能为你的学习加分。如果你没有很多的编程经验,没关系,你会很快捡起来的!
如果你是Windows操作系统,你依然可以通过CygWin或MinGW编译Objective-C。这个教程是针对Mac用户的,如果你在使用Windows时遇到了任何问题请留言,我会尽我所能帮助你。

编译你的代码

在你编写代码之前,你需要知道如何将代码编译成可执行文件。希望你已经安装了GCC环境。编译是非常简单的,一个简单的命令行即可。

注意:
编译是将高级语言(例如Objective-C或者PHP)翻译成机器码的过程,生成的机器码才可以被计算机运行。
所有运行在Mac操作系统上的程序包含了一系列的指令用于显示可见的GUI(图形用户接口)。GUI编程和我们熟悉的鼠标交互相对比,它可以通过文本接口,即我们所熟知的终端或者命令行更加直接的控制操作系统。

Mac操作系统中的命令行应用被称作Terminal,可以通过Applications -> Utilities中找到。现在去打开Terminal,为了方便使用,有一些指令需要注意。最常用的一个是“cd”,表示改变路径。这个命令可以改变Terminal读取的文件系统路径。我们必须告诉Terminal需要编译的文件目录。可以输入全路径,通过下面的命令跳转到一个目录:

cd /Users/MyName/Desktop/Test

我们也可以使用相对路径,在某些情况下只用输入单一的文件夹名。例如:如果你已经在Desktop文件夹下,你只用简单的输入:

cd Test
来进入Test文件夹。

如果你想知道当前路径是什么呢?当前文件路径在提示符(你输入字符的位置)前面显示。比如,你的提示显示Dan- Walkers-MacBook: Desktop iDemonix$,那么你就在Desktop文件夹下。如果你不太确定,也可以通过输入pwd命令来显示当前目录的绝对路径。
如果你想列出当前路径下的所有文件和文件夹,使用ls命令。最后,如果你想跳转到上一层目录,使用“cd ..”。如果我们在Desktop文件夹中的Test文件夹下,但是想跳转到Desktop文件夹下,可以输入“cd..”,来跳转到上一层目录Desktop。如果我们想跳到家目录下,可以输入cd ../..来跳出两级目录。或者在任何目录下使用cd ~命令,来跳转到家目录。
使用Terminal时,编译方法如下:

gcc inputfile.m -o outputfile
你应该已经猜到了它是如何工作的: inputfile.m文件中包含着我们的代码(.m是Objective-C文件的后缀),-o 告诉gcc我们想执行生成的文件,像例子中的outputfile文件。可以通过下面的命令执行编译后生成的文件:

./outputfile
编译的过程中根据代码的语法可能会生成错误、通知或者警告。错误指的是编译过程中产生的编译时错误,它是编写代码过程中最令人紧张的部分(尤其是你的代码因为有一个字符的位置错误或者忘记在每行的末尾加分号而编译错误时)。当你编写由多个文件组成的大型应用时,编译可能花费一段时间,这也是编译令人紧张的另外一个原因。我们经常能看到一个蓬头苟面的程序员在T恤上写着“我没有偷懒,我的代码正在编译”。

基本点

Objective-C本身不是很难学习. 一旦你掌握了基本原则,你可以很简单的上手。你需要理解C语言编程的基础,这在后面的教程中会涵盖到。
让我们看下最基本的C应用:

#include <stdio.h>
int main(){
    printf("Hello World\n");
    return 0;
}

当运行这个应用的时候,它会在Terminal中显示 "Hello World" 然后退出。

注意:
你是否好奇"return 0"这个语句的作用?因为我们告诉编译器main()函数会返回一个整数,我们在函数的最后返回了一个整数“0”。返回“0”是告诉调用程序,我们的程序已经正确执行完毕。

你可以自己打开Xcode,新建一个Objective-C类,删除Xcode中自动生成的代码,将上面的代码贴进去。然后就可以使用Terminal进行编译了。打开Termial并且跳转到文件所在目录,如果你保存到了桌面,那么就输入cd desktop,这样Terminal就从桌面读取文件。然后输入下面的命令:

gcc program1.m -o program1
你的代码应该没有错误,然后运行它:

./program1

回车。

很棒!看看发生了什么?首先我们导入了一个叫做stdio的包,这个包用于管理标准i/o(输入输出)函数,如printf()。我们新建一个函数main,它会返回一个整数。然后使用printf()函数在终端输出ʻHello Worldʼ,\n用于告诉终端此处需要换行。最后,我们返回一个0来告诉操作系统返回正常。我们使用main来命名函数是因为它能被系统自动调用。

到目前为止所有都很简单:我们希望向终端输出一些文字,所以我们引入了一个可以输出文字的包,然后调用了一个函数打印文字。想象一下你引入了一个实物的包,而printf()是这些实物中的一本书。

变量

接下来我们开始介绍变量。应用中最基本的一件事就是要存储临时数据。我们通过变量来实现它。变量可以用于存储不同类型的数据并且有不同的操作方式。我们用变量来存储不同的数据,但是必须首先告诉编译器我们要存储什么。下面是一些重要的变量类型,你必须知道它们:

  • int - 用于存储整数 (没有小数点的数)
  • char - 用于存储字符
  • float - 用于存储小数
  • double - 和float类似,但是精度比float多一倍

有时我们会使用常量,常量是不会变化的:我们知道这个常量的值。如果我们对两个常量进行加法,这个表达式将会这样写:

123 + 2 = 125

这是一个常量表达式,123 + 2 永远等于125。如果我们将一个常量换成变量,那么新的表达式如下:

123 + i = ?

因为i是一个动态的变量,我们不确定它的值,我们可以把i改成任意的值然后得到一个不同的结果。这就是变量如何工作的。

我们还需要知道如何像显示“Hello World”一样显示变量。我们依然使用printf()函数,除了一点小变化:

#include <stdio.h>
int main(){
    int someNumber = 123;
    printf("My number is %i \n", someNumber);
    return 0;
}

我们在这里需要做的是告诉printf()函数整数要在哪里显示,它的值是多少。这和很多语言(如PHP)不同,它们只需要将变量写在文本中。

在printf()函数中可以有多个变量,它们用逗号分割开。我们可以传递多个格式化标志。上面我们使用了%i作为格式化标志因为i是一个整数。其他类型变量有着自己的格式化标志:

  • %i - integer
  • %f - float
  • %e - double
  • %c - char

在讲述char类型之前要主要的是,一个char变量只能存储单个字符,对于字符串是无效的。为了解决这个问题,我们需要使用字符数组。

如果一个句子有11个字符(比如 ʻHello Worldʼ,不要忘记了句子中的空格),一个字符串数组像11个字符,但是它们是连接在一起的。这就说明了虽然数组的值是 ʻHello Worldʼ ,但是char[0]是‘H’。括号里的值代表了数组中的第几个字符,0是第一个字符,而不是1。

条件

当一个应用需要做决定时,我们使用条件。如果没有条件,每次运行应用得到的会是同一个答案,就像看一部电影。通过变量的值做选择,我们可以使得应用有变化。这会和用户输入几个数字或者按下10次按钮一样简单。

条件有几种不同下形式,这里只关注最通用的一种,if表达式。if表达式和它看上去的一样,它检查表达式中的内容是否为真,然后最对应的处理,如:

#include <stdio.h>
int main()
{
    if(1 == 1) { // This is always true
        // Do some stuff here
    }
 
    return 0;
}
如果1等于1,那么花括号中间的部分会被执行。你也许会想,为什么要用两个等号来表达相等而不是一个。两个等号是相等操作符,它检查两边的数值是否相等。如果使用一个等号代表我们试图将第一个值赋给第二个值。
由于1等于1是恒定的,括号中的部分总是会被执行。如果if部分不为true的时候会怎样呢?这就是else的作用。

int main(){
    if(1==1){
        // Do some stuff here.
    }
    else{
        // The universe is broken!
    }
 
    return 0;
}

当然,在显示生活中,我们不会检查1是不是等于1。但是一个如果一个应用需要点击三次按钮才能退出的话(这虽让人恼怒,但是是有意义的)。你可以检查它被点击了多少次,如果次数小于3,将会执行else语句告诉用户还需要点击多少次才能退出应用。

后面的文章还会进一步讨论关于条件的用法。

循环

循环有三种形式,从使用频繁度来排列,分别是:for, while和do。它们都可以用来循环的执行一段代码,但是作用不同,来看下面的例子:

// if loop
int main () {
    int i = 9;
    int x = 0;
 
    for (x = 0; x < i; x++){
        printf("Count is: %i\n", x);
    }
 
    return 0;
}

这可能看上去很复杂,但实际上没有那么复杂。圆括号后面分别是变量初始化,一个条件和一个动作。当循环开始时会先执行变量初始化,在这个例子里是将0赋给x。每次循环(包括第一次)会检查条件,x是否小于i?最后,当循环结束时,会执行动作-也就是将i的值加1。由于x每次都会加1,它的值一定会大于i,此时循环结束,程序继续向下运行。

// while loop
int main () {
    int x = 0;
    while (x < 10){
        printf("Count is: %i\n", x); //Watch OUT! Something is missing. 
    } 
 
    return 0;
}

与for循环类似,while循环会执行花括号部分的代码直到循环条件为false。由于x是0且在代码中没有改变它的值,上面的循环会一直进行,我们称之为死循环。如果你想将x的值增加,你可以在花括号中间添加如下代码:

// while loop
int main () {
    int x = 0;
    while (x < 10){
        x++;
        printf("Count is: %i\n", x);
    }
 
    return 0;
}

除了条件在语句之后运行这点和while循环不一致之外,do循环本质上是while循环。这就意味着do循环一定会运行一次花括号之间的内容:

// do loop
int main () {
    int x = 0;
    do {
        x++; 
        printf("Count is: %i\n", x);
    } while(x < 10);
 
    return 0;
}

指针

很多刚接触C的开发者指针感到非常困惑。想立刻弄明白指针的作用是很困难的,但随着学校时间的推移,你会逐渐理解它。那么,什么是指针呢?

通过字面的意思,指针是指向位置的。具体来说,这个位置就是计算机内存。你可以这样想象,我们声明了一个变量(它是一个名为foo的整数,在计算机理论中很流行这样的称谓),它的值为123。现在我们让一个指针指向foo,这样我们就可以访问它。也就是说,我们有一个int类型的指针指向foo变量,变量中存储的值为123。我们用如下代码表示这个 过程:

int foo = 123; // This is an integer variable
int *ptr = &foo; // This is a pointer to an integer variable

不是很清楚?不用着急。指针非常难理解-通常他被认为是学习C语言中最难的部分。你会慢慢习惯指针,后面我们会继续介绍Objective-C中的指针。

进一步

我们刚对C语言的基础有一个简单的了解,这部分的内容是为了对C有个快速简明的了解,以便更好的学习下面的课程,尤其是对于已经有其他语言基础的人。如果你没有编写过程序或者对C的基础还是不理解,请重新阅读你感到困惑的部分。

在下次学习之前,请确保已经编译过上面出现的代码。试着给自己一些小挑战,比如写一个可以运行10次的循环,每次打印出循环次数。重复练习是非常有益的,如果出现错误,你可以自己尝试去调试它。

挑战

本周我们以一个简单的练习结束。你需要用三种不同的循环方式写三段代码从1数到10。由于循环在Objective-C中是非常常见的,你需要了然于心。这非常简单,你可以试着从10数到1(如果++代表加1,那么减1又该怎么表示呢?)。

下次

下次我会简单的介绍Objective-C是如何工作的。我们也会介绍面向对象编程,同时会介绍类、实例、方法、继承等。

下次的课程可以帮助你理解Objective-C为什么是如此美妙以及它为什么继承了如此多C的特性。

如果你遇到了任何问题

如果你遇到了任何问题,你可以在评论中留言,我会不时来看看,或者直接在Twitter (http://www.twitter.com/iDemonix) 上留言,我会尽快回复。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值