Xcode及obj-c的基础知识

Posted 莫霏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xcode及obj-c的基础知识相关的知识,希望对你有一定的参考价值。

 1, 从简单的例程来看基本语法:

        下面的代码是通过OSX-Application-Command Line Tool生成的:

        #import <Foundation/Foundation.h>

 

        int main(int argc, const char * argv[]) {

            @autoreleasepool {

                // insert code here...

                NSLog(@"Hello, World!");

                NSLog(@"Hello, Objective-c");

             }

            return 0;

        }

    1>,文件名:First_OSX_eg.m 这个是OC专用的扩展名,c语言的扩展名一般是用.c,库文件用.h;c++的扩展名一般用.cpp;

         而OC的扩展名都是用.m(来自单词message)不过这个只是阐述部分的扩展名,声明部分的扩展名也是用.h,而且文件名与对应.m的文件是同名,如果扩展名为.mm则可以认为这个单元是c++代码(c++是兼容c的).

    2>,#import相当于C语言中的#include,Delphi语言中的Uses,表示对库文件或其他单元的引用.虽然OC也兼容#include,但是#import要比#include好得多,不管你在文件中出现了多少次#import引用,编译器对特定文件就只引用一次.

        #import之后所用的库文件,在语法上,使用双引号或者尖括号都是允许的,但是一般系统默认为双引号为本地头文件,

而尖括号里跟的时系统头文件.

    3>,<Foundation/Foundation.h>表示引用Foundation框架中的Foundation.h文件.用花键+单点可以查看对应的单元文件.其实,在引用系统库时,一般头

         文件都是几十上百个头文件的集合.#import可以预编译头文件,使得引用速度加快. 例如Foundation.h对应的框架文件可以在以下路径进行查看:

         /System/Library/Frameworks/Foundation.framework/Headers/  (后面版本的Headers目录改成了Resources目录).

     4>,NSLog函数,其中NS表示OSX中基础Cocoa库,最早引用于Next-Step架构,其意义和用法基本等同于C语言中的printf(),但是其参数需要一个Cocoa库

         格式的字串.类似这样的NS命名的函数还很多,例如:

         NSArray: 用来定义一个数组

         NSDateFormat: 格式化日期

         NSThread:定义一个线程.

         NSSpeechSyntheSizer:定义一个声音.

     5>,用@“xx”来表示一个字串,其中@的意义是指这个字串是一个Cocoa库中的NSString字串,而不是传统的C语言字串.作为一个Cocoa风格的字串,其功能

         要比传统的C语言字串强大得多.例如用StringWithFormat方法就可以用格式化字符(例如%d)格式化各种类型数据.

     6>,花+~可以很方便的在多个工程中切换.

2, 常用的OC对象类型: 

 

       1>,UIView : 所有可视控件的基类。基于此类的每一个对象都是一个容器。

        

 

       2>,UILabel:标签类

       

 

       3>,UITextField:文本输入类

       

  

       4>,UIButton: 按钮类

       

 

 

3, 常用的OC语法:

       1>程序流程控制

        a>, 选择结构:

             if(BOOL表达式)

             {

                 表达式;

             }

             else

            {

                表达式;

            }

        b>,循环结构:

           int i;

           for(i=0; i<=99;i++)

           {

                NSLog(@“%d\n”,i);

           }

          或者 

          while(BOOL表达式)

          {循环体}; //这个需要在循环体中对BOOL表达式进行控制.

        c>,分支结构:

           switch(表达式)

           {

               case 分支1数值: 表达式;

                      break;

               case 分支2数值: 表达式;

                      break;

               …

           }   

’       2>, 函数定义:(注意,在Obj-c中,不允许在一个函数内部直接定义子函数.每个函数的作用范围自动是从

              上至下,可以通过声明来作用全局,或者提供给其他单元接口),函数允许参数名与函数名同名.

            如果函数的返回值类型为一个类的对象,则函数应该用指针型,例如:

        NSString *ShowMsg(int x1)

        {

            return([NSString stringWithFormat:@"%d",x1]);

        }

            如果是调用这个函数返回值,可以用%@格式字串例如:

           NSLog(@"%@",ShowMsg(123456));

       关于默认的main函数定义:int main(int argc, const char *argv[])

          其中,argc为程序的参数个数,argv为参数数组,其中argv[0]为程序文件本身路径+文件名(这点与Delphi相同).

 

        3>,  数据类型的定义(对于对象的定义一律用指针)

          a>, 整型: int a;

          b>, 字符类型: char c;

          c>, 字符串类型: 

               char s[n]; 这个相当于n长度的数组,而对应Cocoa库则为NSArray. 这里s即为一个指针,相当于字符串对象名.

               char s[]; 可以这么定义一个变长的数组,Obj-c中的字符串严格按对象处理,不像Delphi中那么方便了. 

               可以用strlen(s)来返回一个字串的长度.

               char *s[];可以用这个来定义一个多维数组,其中每一个s[i]对应一个字串.

               NSString str; 不过由于Obj-c中常使用Cocoa库的NSString,所以大多数时候,尽量使用这个类型,它带有很多方便的方法.

          d>,BOOL类型: OC的布尔类型并不是true和false,而是YES和NO. 其本质是一个8位的带符号的字符.定义时,1为YES,0为NO.在实际使用时,如果把其他符号

                当作BOOL类型判断,那么只会判断其最低位的值,而忽略高位值(注意这里跟C语言不同,并不是大于0就为真).

                对BOOL类型值的判断,只能拿值与NO进行比较,如果相当为假,不等则为真.无法用BOOL类型与YES进行比较(虽然有时候用YES比较也恰好正确).   

          e>,浮点型float

          f>,常量关键字const 这个可以加在定义类型前,例如:const char *argv[];

          g>,枚举类型的定义:

              typedef enum{ 枚举常量列表,逗号隔开} 枚举类型名;

              并没有具体的内部函数可以直接得到枚举常量名,可以自己构造一个函数来实现.

              常用的枚举定义技巧,可以定义一个起始量和一个终止量,这样方便循环遍历.

          h>,结构体类型定义: 

              typedef struct{结构体元素定义}结构体类型名;

              对结构体赋值可以直接用大括号包含数值: stru1={1,’a’};

              也可以用[结构体变量名.成员名]引用每一个成员进行赋值.

        5>,更为复杂的一些Cocoa定义的有用数据类型.

            a>NSRange:

            typedef struct _NSRange{

                     unsigned int location;

                     unsigned int length;

             } NSRange;

             表示一段数据的起始位置以及数据长度.

             可以利用快捷函数NSMakeRange()来返回一个NSRange

             eg. NSRange range=NSMakeRange(17,4);

 

             b>若干几何数据类型:NSPoint, NSSize,NSRect

             对应快捷函数NSMakePoint(), NSMakeSize(),NSMakeRect()

            typedef struct _NSPoint{

                      float x;

                      float y;

             } NSPoint;

 

             typedef struct _NSSize{

                      float width;

                      float height;

             }NSSize;

 

             typedef struct _NSRect{

                       NSPoint origin;

                       NSSize size;

             }NSRect;

 

             c> NSString, 相比c语言中的字符串与字符数组的关系,不需要再考虑0操作字符.

            

 

 

        6>, 文件类型定义: FILE *words;  words=fopen(argv[1],”r”);   

              上面这两句也可以在定义时直接赋值:FILE *words=fopen(argv[1],”r”);   

              fgets(word, 100, words);  这个函数用来读取一个文本文件内容,其中word为一个数组用来接收数据,100读取长度,words为文件类型.

              其返回值为BOOL型,读取文件时,遇到换行符自动结束本次读取,并且将文件的位置标志置于下行开始.

              可以用这个语句将读取的内容转为字符串:word[strlen(word)-1]=‘\0’; 反斜杠0是空操作字符用来表示字符串结束.

              文件标准路径的写法:/Users/Murphy/…

 

 

      每一个用户,均有以用户名命名的根目录文件夹结构,其对应的系统文件夹路径如下: 

      公共:/Users/用户名/Public

      图片:/Users/用户名/Pictures

      文稿:/Users/用户名/Documents

 

5,类与对象的使用

        1> 类的定义,可以分为两个部分,一个部分是声明部分,一个部分是阐述部分:

         //声明部分用来描述定义各个成员和方法,格式如下:

         @interface 类名 :基类名  //这里基类名可以使用NSObject, 或者其他基类。

         {    

              @public/@private/@protected  //其实Obj-c并不存在真正的私有方法.这是Obj-c的动态本质决定的.

              成员定义区;  

         }

         @public/@private/@protect

         方法定义区;     //方法可以用加号或者减号来对应类方法或者成员方法.如果没有加减号,则是函数原型.

         e.g. -(void) setmember : (类型)参数;

         @end

 

’     //类的声明部分主要是针对其方法进行的,格式如下:

        @implementation 类名

        -(void)方法名 : (类型)参数

        {

            方法实现;

        }

       @end  //类名  在结束符后,添加类名,是一个好的习惯,可以增加程序的可读性.

          这里注意,方法的返回值也是需要类型定义的,一定要用加减号(类型)的形式来说明,括号不能省略.同样,参数的

          类型圆括号也不能省略.

          在@implementation中允许出现无声明的方法,这种方法可以看做是类私有方法(与Delphi相同).

          在@implementation部分的参数名可以不与@interface部分相同.注意,在@implementation中使用的参数

          最好不要与@interface部分的成员变量同名,否则会隐藏实例变量,并生成警告信息.

          如果想调用隐藏的实例变量可以用self->成员名来进行.

 

       2>类和对象的使用语法:

          a> 在Obj-c中,所有对象的原基类都是NSObject,(这相当于Delphi中的Object).

          b>Obj-c中的所有成员变量的定义,均是 类型名在前,变量名在后.并且在定义的时候就可以直接赋值.

          c>Obj-c的中缀符调用方法:

             [对象名 方法名: 参数];

             这里方法名和冒号可以看成是一体的,它告诉编译器后面会出现参数.而在不含参数的方法后面添加冒号会报错.

          d>类的公共接口称为API(application programming interface)

          e>在方法体中,允许使用self来访问对象本身.

          f>NSObject类具有一个类方法new,(相当于Delphi的构造方法).我们可以通过调用这个方法得到一个实例.

             [类名 new];   // 当然所有类方法,都可以用向类名发送消息的方法进行调用.

          g>id 可以用来定义一个通用对象变量,它可以指向任何对象,并且可以用id 来定义一个数组,然后每个数组元素

             都指向不同类的对象.  //这里有个疑问,为什么不直接用NSObject代替id,不过我好好研究了下,发现id跟Delphi

             中引用Object还真是不同,id 定义的对象,你可以直接向它发送各种子类消息,而不需要用as 进行类转换.

       3>类继承的实现:

           a>Obj-c废弃了C++多继承的特性,在Obj-c中是不允许多继承的.(这点跟Delphi是一样的).

           b>Obj-c在声明的时候,是没必要像Delphi那样用virtual或者dynamic来声明虚函数的.

               只需要在子类覆盖此方法的时候,在阐述部分使用super关键字,即可完成继承.其调用父类部分格式为:

               [super 方法名称:参数];  //即完成了对父类虚方法的调用,类似Delphi中的inherited; 但是这个语句是写在覆盖

               函数之外的.

               super关键字,会沿着超类链持续往上级查找,直到找到父类的方法.

       4>类的复合:

           将若干个对象组合在一起,并且形成一个新对象的过程就叫复合.

           每一个组合子对象都可以看作是母对象的一个属性,而对每个属性都可以用同名的getter和setter方法来进行

           存储,一般都是成对出现,其格式如下:

          -(子对象类*) 子对象名;  //这里省略掉了对应的get关键字,除非getter方法需要用到指针形参才会添加get

          -(void) set子对象名:(子对象类型*) new子对象名; //这里的形参最好不要与原对象同名,

           set后跟的对象名,第一个字母一般习惯大写.

          注意,当使用setter方法进行属性设置时,被替代的数据其实是属性的指针,而不是真实值.由于Obj-c的对象引用

          机制,我们不需要考虑到这里的主动释放,这跟Delphi是不同的.

 

          属性的自我构造,可以使用init函数来实现,在定义属性类中,用以下语句可以实现属性对象的自我构造:

          注意init方法属于对象的内部方法,是不需要在@interface部分主动声明的.

          @implementation 母对象名

          -(id)init

          {

              if(self=[super init]){

                  属性名=[属性类名 new];

              }

              return(self);

          }//init

          …

          @end

          这样就形成了属性的自我构造,不过如果属性有相应的setter方法,其实不用构造也可以,不过使用时需要主动赋值.

       5>头文件的拆分,指向,导入和继承:

           在用.m文件和.h文件拆分复合类时,需要在复合类的头文件中用  @class 类名  指向其复合的属性类.

           而在复合类的阐述文件中,不仅仅要用#import导入其对应头文件,也必须用其导入对应的所有属性类的头文件.

           而在派生类拆分文件时,派生类的头文件,只需要导入父类的头文件就可以(可以完全忽略父类中已有的系统头文件)

       6>面向对象的设计意义:

           a>在面向对象和面向过程的设计中,最大得差别是其功能修改增删时的改变方式.面向对象可以避免修改到整体

              的处理函数,也不需要修改基本的结构体,只需要增加一个类基本就可以适应变化了.

           b>面向过程的设计是函数第一,数据第二,这导致程序修改经常会影响到接口;而面向对象的设计,可以直接吧原先

              函数修改的部分巧妙的移动到对象的方法之中,我们只需要关注对象这个数据就好了,不会影响到函数和接口.

           c>当不同类中出现了大量的重复的代码,就绝非优良的设计,我们可以更改其类的继承结构,使这些重复代码在中间

              的继承类中实现,这种移动和简化代码的方法称为重构.

           d>当你创建的新类与现有类是is a 的关系就可以使用继承;当你创建的类与现有类是has a 的关系,就需要用到复合了.

        7>面向对象的术语:

            a>超类:superclass

            b>父类:parentclass,同超类.

            c>子类(派生类):subclass

            d>孩子类:childclass,同子类.

 

6,常用的XCode操作技巧

     1>花+[ 和 花+]可以将选定得代码块左移或者右移

     2>ESC键可以关闭和打开自动完成的选择框.

     3>Control+/ 可以在输入时自动跳在占位符上.

     4>花+Control+S可以建立一个快照.

     5>花+Shift+O 快速打开一个单元文件.

     6>Control+F/B 分别是前移光标和后移光标.

     7>Control+P/N 分别是上移光标和下移光标.

     8>Control+A/E 分别是移动光标到该行的行首和行尾.

     9>Control+T 把光标前的字符往后拖一个位置.

     10>Control+D 删除光标右边的字符(相当于windows中的Del键).

     11>Control+K 删除一行.其实这个是删除当前行光标后面的部分.

     12>Control+L 调整窗口,以便将当前的光标居于窗口中心.

     13>花+Y 以调试方式运行程序.

     14>花+Option+P/O/I/T  分别是调试的 继续,跳过,跳入,跳出.

 

     

      

        

    

 

以上是关于Xcode及obj-c的基础知识的主要内容,如果未能解决你的问题,请参考以下文章

“仅显示 Obj-c”标志隐藏 xCode Instruments 上调用树的所有内容

Obj-C - Xcode 控制台中的 TIC 读取状态?

使用 setDataSource 升级到 Xcode 4.6 后出现编译器错误

xCode 4.6.3 蜡框架

Xcode 基础工程结构解析

# 通过自动创建的 Bridging header 导入 Obj-C 类, Bridging header 似乎找到它但 Swift 类不会