在新建文件时选择os x列表下的“source”,再从右面的选项中选择“cocoa class”,填写类名以及选择存储位置后会自动生成2个文件:一个.h文件和一个.m文件,格式如下

student.h:

1
2
3
4
5
6
7
#import <Foundation/Foundation.h>
@interface Student : NSObject
@end</pre>
student.m:
<pre class="lang:objc decode:true">#import "Student.h"
@implementation Student
@end

其中.h文件中定义类的属性、方法,和C++一样,OC中的属性也分为3种,private、protected、public。不过方法都是public的,而且不支持重载,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#import <Foundation/Foundation.h>
@interface Student : NSObject{
@protected
NSString * name;
unsigned int age;
@public
NSString * sid;
}
-(NSString *) getName;
-(void) setName:(NSString *) aName;
-(unsigned int) getAge; //无参数,冒号被省略
-(void) setAge:(unsigned int) aAge;
-(void) setNA:(NSString *)aName age:(unsigned int)aAge;
-(void) setNA:(NSString *)aName :(unsigned int)aAge; //同上 2个参数 age被省略 貌似变成了2个不同的函数
//-(int) getName; //oc不支持重载,所以即便返回值类型不同也不能重名
+(void) testfuc; // + 类方法
@end

和C++不同的地方就是声明一个类的语法不再是class而变成了@interface,上面这个student类继承自NSObject,这个基类和python中的object基类类似,提供了一些基本的构造函数、析构函数等来进行初始化以及回收操作。而且,oc中方法的声明和实现是写在两个文件中的,那个.m文件中写的就是方法的具体实现代码,下面再说。

类的继承以及属性的定义还比较容易理解,不过下面那些神码加号、减号、冒号的又是神码玩意??这种语法也太奇怪了吧?这里说说我个人的理解,如果有神码错误的地方,等以后学的更深入了再来改吧。

首先,+、-这两个符号定义了这个函数究竟是实例方法(-)还是类方法(+);

接着的括号中定义了函数的返回类型;

再接下来是函数名,这里是让我感到比较别扭的地方,比如

1
-(void) setNA:(NSString *)aName age:(unsigned int)aAge;

调用时候使用setNA这个函数名即可,不过后面的age也算是函数名的一部分,而这部分又可以被省略掉……上面说过OC中不支持函数的重载,即便参数类型和函数的返回值不同的情况下函数名一样也会报错。不过再声明一个函数比如:-(void) setNA:(NSString *)aName otherage:(unsigned int)aAge;

或者省略掉后面的参数名却是可以的,因为此时省略了后面函数名就代表着这是2个不同的函数了。

最后是一个“:(参数类型)参数名1 可省略的函数名:(参数类型)参数名2…”不考虑那个分家了的函数名的话这里也是比较好接受的。

所以,一个函数的声明整体来说结构如下:

+ or - 函数名:(参数类型)参数名1 可省略的函数名:(参数类型)参数名2….;

接下来进入.m去实现上面声明的函数,偷懒的办法就是把声明函数的代码复制过来,再把;替换成{}即可…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#import "Student.h"
@implementation Student
-(NSString *) getName{
return name;
}
-(void) setName:(NSString *) aName{
name = aName;
}
-(unsigned int) getAge{
return age;
}
-(void) setAge:(unsigned int) aAge{
age = aAge;
}
-(void) setNA:(NSString *)aName :(unsigned int)aAge{
name = aName;
age = aAge;
NSLog(@"setna 1");
}
-(void) setNA:(NSString *)aName age:(unsigned int)aAge{
name = aName;
age = aAge;
NSLog(@"setna 2");
}
+(void) testfuc{
NSLog(@"is a class fuc");
}
@end

最后就是在主文件中引入我们写的类以及创建对象了,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student * astduent = [[Student alloc] init]; //oc中内存都在堆上分配,所以要指针类型
//Student *bstduent = [Stduent new]; //另一种方式创建
astduent->sid = @"nsstring";// public属性直接访问
[Student testfuc]; //类方法调用
[astduent setName:@"abc"]; //实例方法掉用
[astduent setNA:@"abc1" : 15];
[astduent setNA:@"abc2" age:17];
NSLog(@"student name is %@",[astduent getName]); //getName其实是一个返回NSString类型的函数
NSLog(@"student age is %d",[astduent getAge]);
}
return 0;
}

至于@ [ ]的意思上文中已经说过了,至于alloc、init方法就是在基类中定义的,至于第二种方式引用一下别人的解释吧:

new方法是NSObject对象的一个静态方法,根据apple的文档,该方法实际上就是alloc和init方法的组合,实际上二者是一样的,但 apple还是推荐我们使用第一种方法,为什么呢?因为使用第一种方法,你可以使用自己定义的init方法来做一些初始化,当然,如果子类没有提供 init方法,自然调用的就是父类的init方法了。所以说,从安全性的角度来收,作为开发者我们在对象使用之前是一定要对对象进行初始化的,因此在定义类的时候一定要提供初始化方法。但是否一定要使用init作为方法名呢?答案是不一定。使用init作为方法名只是你重写了NSObject的init方法而已,如果你自己重新定义一个初始化方法,也是完全可以的,只要你在使用的时候记得调用新定义的初始化方法就可以了。

引用来源:http://www.oschina.net/question/54100_32468

最后看输出,也说明了上面的一点:

1
2
3
4
5
2015-02-11 21:52:43.506 helloword[1069:146145] is a class fuc
2015-02-11 21:52:43.507 helloword[1069:146145] setna 1
2015-02-11 21:52:43.507 helloword[1069:146145] setna 2
2015-02-11 21:52:43.507 helloword[1069:146145] student name is abcd
2015-02-11 21:52:43.507 helloword[1069:146145] student age is 17

评论和分享

很多人为了学习ios开发而买了mac,而我却正好相反——买了mac后觉得只拿来看看网页、管理服务器什么的太浪费了,就顺便把ios开发也学学吧。由于本人是oc初学者,若有错误的地方还请指正。本文使用os x 10.10.2以及xcode 6.1.1。

这里首先面临的就是语言的选择——oc和swift。经过“深思熟虑”我还是选择了oc,因为相关的资料比较多,遇到问题google起来效果较好。很多人觉得ios开发很难学是因为oc——别的不敢讲,就我这两天的学习来看,oc虽说是c的超集,不过语法看起来题确实挺奇怪,但对于任何有其他语言开发基础的人来说,语法仅仅是一个需要习惯的过程。ios开发的真正难点在于cocos引擎部分,所以对于英语好的来说swift也是不错的选择(英语硬伤还是啊……)。

直接从appstore中安装xcode,安装完成后运行选择“create a new Xcode project”,再选择os x列表下的“application”,然后在右边的窗口中选择“command line tool”,点击“next”后输入项目名称等相关信息,语言选择“Objective-c”,再选择保存位置后点击“finish”即可。

点击左边列表的main.m文件就是程序自动生成的模版文件了,代码如下

1
2
3
4
5
6
7
8
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}

这个像c语言又不是c语言的家伙就是oc了,又感觉有些python影子,比如引入头文件的语法变成了import,释放内存池的语法@autoreleasepool和python的装饰器语法、功能相似等。虽然oc也是用.h做头文件后缀,不过却用.m做代码文件后缀。

第一行的Foundation/Foundation.h作用类似stdio.h或iostream,定义了很多核心函数在里面,比如NSLog,这个函数功能就是输出,和printf一样,不过里面那个@又是神马东东呢?

这里就要引出oc中的一个新类型——NSString,字符串。动态构建NSString有2种方法:

NSString *str = @"is a number";
NSLog(@"%d  %@",1,str);
NSString *str1 = [[NSString alloc] initWithFormat:@"%d + %d = %s",1,2,"3"];
NSLog(@"%@",str1);
//[str1 release];

由于oc中内存都是在堆上分配的,所以返回的都是指针(至于原因这里先留个坑,我也没太深究),注意占位符和%d、%s类似,不过变成了“%@”代表这是个NSString类型(换言之@是否就是代表这个类型呢?)。第三行的alloc作用和c中的malloc一样,分配内存的。大小为NSString类型大小,并且用后面的参数进行格式化。

这里可能还有个疑问,那个[]又是神马意思呢?难道是python的列表?据目前所学知识,[]是oc中调用函数的方式,这个在后面的学习应该还会遇到。

最后一行又是神马意思呢?为什么又注释呢?从字面意思来看,明显和内存释放有关。不过由于最新版的xcode默认开启了arc,所以在这种情况下写这句代码会报错。不过在之前的某些版本中,如果关闭了arc则申请了内存后一定记得释放。

评论和分享

  • 第 1 页 共 1 页
作者的图片

Roy

微信公众号:hi-roy


野生程序猿


China