Objective-C初探

Objective-C简介(简称OC)

基于C语言,增加了最小的面向对象语法,完全兼容C语言

MacOSX和iOS平台的开发语言

可以购入C、C++代码

OC语法纵览1

OC中没有类似Java中的包名这个概念,取而代之的是程序设计师必须给类名加上前缀,使用前缀可以有效的防止名称冲突。

如NSString、NSArray(前缀都是NS)

为了避免跟C、C++的关键字冲突,所有的OC关键字以@开始,比如

@interface,@implementation,@end

@public,@protected,@private,@selector

@try,@catch,@throw,@finally

@protocl,@class

OC2.0中引入的新关键字有

@property,@synthesize

@optional,@required,@dynamic

OC语法纵览2

基本数据类型int、float、double、char、Bool(YES/NO)等

id类型每个对象都可以表达为id类型,可以认为是NSObject*或者void*

nil等同于NULL

基本语法循环语句(dowhile、while、for)、条件语句(if、ifelse、switch)、Boolean(YESNO)、条件运算符、goto语句、空语句、逗号表达式、sizeof运算符、命令行参数、位操作都和C一样

for循环扩展for(xxinxx)

基类NSObject

继承单继承

多态支持多态

抽象类支持抽象类

异常处理@try@catch@finally

日志输出NSLog(@"HelloWorld");NSLog(@"Myageis%i",25);

注释/*......*/和//

OC语法纵览3

OC提供了BOOL类型,但是这个Bool类型和C++里的并不一样;在C++里一切非0值的东西都为true,而为0值为false,但在OC里1为true并被宏定义为YES,0为false并被宏定义为NO

所以,下面的代码,肯定是错误的:

BoolareDifferent(inta,intb)

{

return(a-b);

}

if(areDifferent(23,5)==YES)

{}

因为areDifferent返回的是两个整数的差,如果这个差不为1,那么永远不会YES

类的定义

OC中类分为2个文件

.h,类的声名文件,用于声名变量、函数(方法)

.m,类的实现文件,用于实现.h中的函数(方法)

类的声名使用关键字@interface、@end

类的实现使用关键字@implemantation、@end

方法的声名和实现,都必须以+或者-开头

+表示类方法(静态方法)

-表示对象方法(动态方法)

在.h中声明的所有方法都public类型(通过Category可以实现private)

变量的作用域

@public全局都可以访问

@protected只能在类内部和子类中访问

@private只能在类内部访问

变量必须定义在类的{}中

类的声明-Student

#import <Foundation/Foundation.h>

@interface CLStudent : NSObject
{
    int age;
    int no;
}

-(int) age;  //int getAge()
-(void)setAge:(int) _age; //getAget(int age);
-(int)no;
-(void)setNo:(int) _no;
-(void)setAgeAndNo:(int) _age:(int)_no;
-(void) Age:(int) _age No:(int) _no;
@end

#import "CLStudent.h"  //系统引用框架要用坚括号

@implementation CLStudent
- (int)age{
    return age;
}
-(void)setAge:(int)_age{
    age = _age;
}
- (int)no{
    return no;
}
- (void)setNo:(int)_no{
    no = _no;
}
-(void)setAgeAndNo:(int)_age :(int)_no{
    no = _no;
    age = _age;
}
-(void) Age:(int)_age No:(int)_no{
    age = _age;
    no = _no;
}
@end

#import <Foundation/Foundation.h>
#import "CLStudent.h"

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

    @autoreleasepool {
        
        // insert code here...
        NSLog(@"Hello, World! %i",10);
        printf("Hello, World!");
        
        //分配内存空间  
        CLStudent *temp = [CLStudent alloc];
        //调用构造函数进行初始化
        CLStudent *stu = [temp init];
        [stu release];
        CLStudent *student = [[CLStudent alloc] init];
        [student setAge:10];
        [student setNo:15];
        NSLog(@"age is %i,no is %i",[student age],[student no]);
        [student setAgeAndNo:20 :25];
        NSLog(@"age is %i,no is %i",[student age],[student no]);
        [student Age:21 No:26];
        NSLog(@"age is %i,no is %i",[student age],[student no]);
        [student release];
    }
    return 0;
}

框架

所谓框架,就是一个集合,其中包含着头文件等资源文件

每个框架中均有一个主头文件,该头文件包含了框架中各个头文件,一但引入了主头文件,就可以在自己的程序里使用任何框架里类

比如要使用Foundation框架,就导入它的主头文件即可:

#import<Foundation/Foundation.h>

Cocoa简介

NextStep是一个用Objective-C编写的功能强大的工具包,里面有大量的类库,结构体等,被苹果收购后,更名为Cocoa,但苹果公司并未更改NextStep中的类库名称,因此会有大量以NS为前缀的类名、结构体、枚举等

Cocoa里面的任何类都要继承自NSObject(只有这样,该类的对象才可以获得运行时的基本能力)

Cocoa包含两个核心框架:Foundtion框架和Appkit框架,用于开发MacOSX平台的应用程序

Cocoa框架在iOS上叫做CocoaTouch,包含两个核心框架:Foundation框架和UIKit框架,用于开发iOS平台的应用程序(iPhone\iPod\iPad)

CocoaTouch与Cocoa一个比较鲜明的区别就是CocoaTouch并不支持垃圾回收机制,这就意味着你必须在你的代码里管理好你的内存

常用拓展名

拓展名含义

.h头文件。用于描述类的组件,包含成员变量、成员方法、类变量、类方法

.cc源文件

.cpp.ccc源文件

.mobjective-c源文件,也叫实现类的类文件,可以包含Objective-C和C代码,一般一个.m文件会和一个.h相对应。

.mmobjective-c++源文件,除了Objective-C和C代码,还可以包含C++代码

#import

C/C++中使用#include导入头文件,缺点就是同一个头文件可能被导入多次

C/C++为了防止多次导入同一个头文件

#ifndef_TEST_H_

#define_TEST_H_

#include"test.h"

#endif

OC中使用#import导入头文件,优点是可以自动防止同一个头文件被导入多次

创建/销毁对象

分配内存空间,创建对象

Student*stu=[Studentalloc];

调用构造方法,初始化对象

[stuinit];

销毁对象

[sturelease];

一般来说创建和初始化连着一起操作

Student*stu=[[Studentalloc]init];

/*...........................*/

[sturelease];

构造方法

-(CLStudent *)initWwithAge:(int) newAge;

-(CLStudent *)initWwithAge:(int)newAge{    
    if(self = [super init]){
        age = newAge;
        return self;
    }
    return nil;
}

CLStudent *students = [[CLStudent alloc] initWwithAge:23];
NSLog(@"age is %i,no is %i",[students age]);
[students release];

-(id)initwithAge:(int) newAge andNo:(int)newNo;

-(id)initwithAge:(int)newAge andNo:(int)newNo{
    if(self = [self initWwithAge:newAge]){
        no = newNo;
        return self;
    }
    return nil;
}

CLStudent *student2 = [[CLStudent alloc] initwithAge:24 andNo:26];
NSLog(@"age is %i,no is %i",[student2 age],[student2 no]);
NSObject *obj = [[CLStudent alloc] init];
id obj1 = [[CLStudent alloc] init];        
[student2 release];

实例化二

NSObject*obj=[[CLStudentalloc]init];

NSObject*obj=[CLStudentnew];

注释

#pragmamark-getter注释一类方法

#pragmamark设置年龄单个方法注释

也可以安装额外的服务生成Doxygen文档注释

点语法(调用是set/get方法)

student2.age=10;

NSLog(@"ageis%i,nois%i",student2.age,student2.no);

@property作用

@propertyintage;自动声明set/get方法

-(int)age;//intgetAge()

-(void)setAge:(int)_age;//getAget(intage);

@property(readwrite,getter=getID)intage;

@property(readwrite,atomic,retain)intage;

@synthesize作用

@synthesizeage;自动生成实现set/get方法

内存管理

范围

任何继承了NSObject的对象,对基本数据类型无效

原理

每个对象内部都保存了一个与之相关的整数,称为引用计数器

当使用alloc、new或者copy创建一个对象时,对象的引用计数器被设置为1

给对象发送一条retain消息,可以使引用计数器值+1

给对象发送一条releain消息,可以使引用计数器值-1

当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收,OC也会自动向对象发送一条dealloc消息,一销毁会重写dealloc方法,在这里释放相关资源,一定不要直接调用dealloc方法

可以给对象发送retainCount消息获得当前的引用计数器值

@class

在申明时使用@class

在使用时使用#import

assign直接赋值

自动释放池(autoreleasepool)

自动释放池OC里面的一种内存回收机制,一般可以将一些临时变量添加到自动释放池中,统一回收释放

当自动释放池销毁时,池里面所有对象都会调用一次release方法

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Student *student = [[[Student alloc] init] autorelease];
NSLog(@"%@",student); //[student description]==toString(); [student hash] ==hashcode
[pool release];

Catgory

OC提供一种与众不同的方式-Catagory,可以动态的为已经存在的类添加新的行为(方法)

这样可以保证类的原始设计规模较小,功能增加时再逐步扩展

使用Category对类进行扩展时,不需要访问其源代码,也不需要创建子类

Category使用简单的方式,实现子类的相关方法的模块化,把不同的类方法分配到不同的分类文件中

Category的使用注意

Category可以访问原始类的实例变量,但不能添加变量,如果想添加变量,可以考虑通过继承创建子类

Category可以重载原始类的方法,但不推荐这么做,因为它是直接替换掉原来的方法,这么做的后果是再也不能访问原来的方法,如果确定要重载,正确的选择是创建子类

在分类的实现文件中可以不必实现所有声明的方法,只要你不去调用它

类的私有方法

第一种方式:直接在.m文件中写方法,不要在.h文件中进行方法声明,不然又是公共方法了

第二种方式:在.m文件中定义一个Category(分类),在Category中声明一些方法,然后在@implementation跟@end之间作方法实现

Protocol

简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现,这促模式一般称为代理(delegation)模式

在iOS和OSX开发中,Apple采用了大量的代理模式来实现MVC中View(UI控件)和Controller(控制器)的解耦

#import <Foundation/Foundation.h>
@protocol MyBtnDelege <NSObject>  //实现 NSObject
@required  //必须实现方法  @optional可选
-(void)btnClick:(id)sender;
@end

#import <Foundation/Foundation.h>
@protocol MyBtnDelege;
@interface MyBtn : NSObject
//监听器
@property (retain,nonatomic) id<MyBtnDelege> delegate;
-(void)click;
@end
#import "MyBtn.h"
#import "MyBtnDelege.h"
@implementation MyBtn
@synthesize delegate = _delegate;
-(void)click{
   //通知监听器
   if(_delegate != nil){
      Bool b = [_delegate conformsToProtocol:@protocol(MyBtnDelege)]; //判断协议是否是当前协议
      if(b){
          if([_delegate respondsToSelector:@selector(btnInit:)]){   //判断是否实现方法
          [_delegate btnClick:self];
	  }
      }else{
        NSLog(@"delegate 没有实现相应的协议");
      }
   }
}

-(void)dealloc{
   [super dealloc];
   [_delegate release];
}
@end
#import "MyController.h"
#import "MyBtnDelege.h"
@implementation MyController
-(void) btnClick:sender{
   NSLog(@"按钮%被点击了");
}
@end
#import <Foundation/Foundation.h>
#import "MyBtn.h"
#import "MyController.h"
int main(int argc, const char * argv[])
{
   @autoreleasepool {
     MyBtn *btn = [[[MyBtn alloc] init] autorelease];
     btn.delegate = [[[MyController alloc] init] autorelease];
     [btn click];
   }
   return 0;
}

Foundation框架

NSRange

在Foundation/NSRange.h中对NSRange的定义

typedefstruct_NSRange{

NSUIntegerlocation;

NSUIntegerlength;

}NSRange;

//typedefunsignedlongNSRange;

这个结构体用来表示事物的一个范围,通常是字符串里的字符范围或者集合里的元素范围

location表示该范围的其实位置

length表示该范围内所含元素个数

比如"Iloveobjective-c"中的"obj"可以用location为7,length为3的范围来表示

NSRange

有3种方式创建一个NSRange变量

第1种:直接给成员赋值

NSRangerange;

range.location=7;

range.length=3;

第2种:应用C语言的聚合结构赋值机制

NSRangerange=(7,3);

或者NSRangerange={.location=7,.length=3);

第3种:Foundation框架提供的一个快捷函数NSMakeRange

NSRagerange=NSMakeRange(7,3);

NSRangerange={.location=1,.length=3};

NSRangerange=NSMakeRange(3,4);

NSLog(@"location:%zi,length:%zi",range.location,range.length);

NSPoint

在Foundation/NSGeometry.h中对NSPoint的定义

typedefCGPoint/CGGeometry.h中对CGpoint的相关定义

structCGPoint{

CGFloatx;

CGFloaty;

}

typedefstructCGPointCGPoint

//#defineCGFLOAT_TYPEdouble

//typedefCGFLOAT_TYPECGFloat;

NSPoint和CGPoint是等价的

这个结构体代表的平面中的一个点(x,y)

CGPointpoint=NSMakePoint(10,20);//==NSPointpoint=NSMakePoint(10,20);

NSLog(@"x:%.0f,y:%.0f",point.x,point.y);//.表示小数个数

//等价CGPointMake(10,20);

NSSize

在Foundation/NSGeometry.h中对NSSizer的定义

typedefCGSizeNSSize;

在CoreGraphics/CGGeometry.h中对CGSize的相关定义

structCGSize{

CGFloatwidth;

CGFloatheight;

};

typedefstructCGSize;

这个结构体用来存储宽度和高度

可以利用NSMakeSize()和CGSizeMake()创建CGSize

NSRect

在foundation/NSGeometry.h中对NSRect的定义

typedefCGRectNSRect;

在CoreGraphics/CGGeometry.h中对CGRect的相关定义

structCGRect{

CGPointorigin;

CGSizesize;

}

typedefstructCGRectCGRect;

这个结构体用来存储宽度和高度

可以利用NSMakeRect()和CGRectMake()创建CGRect

NSString的创建

创建常量字符

NSString*string=@"ThisisaString!";

创建空字符串,给予赋值

NSString*string=[[NSStringalloc]init];

string=@"ThisisaString";

通过字符串创建字符

[[NSStringalloc]initWithString:@"ThisisaString!"];

//或者 [[NSStringalloc]initWithFormat:@"Myageis%i",20];

NSString*string=[NSStringstringWithFormat:@"Myageis%i",20];

用标准C创建字符

char*cString="这是一串中文";

[[NSStringalloc]initWithCString:cStringancoding:NSUTF8StringEncoding];

或者 [[NSStringalloc]initWithUTF8String:cString];

//字符串编码可以在NSString.h中查阅

从文件中读取

NSString*path=@"/Users/apple/Desktop/test.txt";

NSStringEncodingenc=CFStringConvertEncodeingToNSStringEncoding(KCFStringEncodingGB_18030_2000);

NSError*error=nil;

NSString*string[[NSStringalloc]initWithContentsOfFile:pathencoding:encerror:&error];//&error指针地址--指向指针的指针

if(error!=nil){

NSLog(@"\n读取错误,错误信息:\n%@",[errorlocalizedDescription]);

}

[stringrelease];

从远程文件读取

NSError*error=nil;

NSURL*url=[NSURLURLWithString:@"http://www.baidu.com"];//NSURL*url=[NSURLURLWithString:@"file:///Users/apple/Desktop/test.txt"];

NSString*string=[[NSStringalloc]initWithContentsOfURL:url,encoding:NSUTF8StringEncoding,error:&error];

NSString文件导出

NSString*string=@"123456";

NSString*path=@"/Users/apple/Desktop/123.txt";

[stringwriteToFile:pathatomically:YESencoding:NSUTF8StringEncodingerror:nil];

[stringwriteToURL:...]//写到远程

NSString的比较

-(Bool)isEqualToString:(NSString*)string

比较两个字符串的内容是否相同,相同就返回YES,不同则返回NO

-(NSComparisonResult)compare:(NSString*)string

逐个字符地进行比较,返回NSComparisonResult来显示比较结果。

NSComparisonResult是一个枚举,有3个值

-(NSComparisonResult)caseInsensitiveCompare:(NSString*)string突略大小写比较

-(NSComparisonResult)compare:(NSString*)string options:(NSString*)string比较字符个数,而不字符

-(NSString*)uppercaseStringstring全部转为大写

-(NSString*)lowercaseStringstring全部转为小写

-(NSString*)capitalizeStringstring首字母变大写,其它字母都小写

NSString的搜索

-(BooL)hasPrefix:(NSString*)string是否以string开头

-(BooL)hassuffix:(NSString*)string是否以string结尾

-(NSRange)rangeOfString:(NSString*)string检查是否包含了atring,如果包含,返回string位置,如果不包含的location为-1,length为0

-(NSRange)rangeOfString:(NSString*)stringoptions:(NSStringCompareOptions)mask可以传递一个mask参数,改变搜索方式 

比如NSStringCompareOptions为NSBackwardsSearch表示从尾部开始搜索

-(NSRange)rangeOfString:(NSString*)stringoptions:(NSStringCompareOptions)maskrange:(NSRange)searchRange还可以用searchRange指定搜索范围

NSString的截取

-(NSString*)substringFromIndex:(NSUInteger)from从指定位置from开始(包括指定位置的字符)到尾部

-(NSString*)substringToIndex:(NSUInteger)to从字符串的开头一直截取到指定位置to,但不包括该位置的字符

-(NSString*)substringWithRange:(NSRange)range按照所给出的NSRange从字符串中截取串

-(NSArray*)componentsSeparatedByString:(NSString*)separator用separator为分隔符截取子串,返回一个装着所有子串的集合NSArray

NSString与路径

-(NSString*)pathWithComponents:(NSArray*)components将components中的字符串比较按顺序拼成一个路径

-(NSArray*)pathComponents将路径分解成一个装着每一个目录的NSArray

-(BooL)isAbsolutePath是否为绝对路径

-(NSString*)lastPathComponent获取最后一个目录

-(NSString*)stringByDeletingLastPathComponent删除最后一个目录

-(NSString*)stringByAppendingPathComponent:(NSString*)str在路径的后面拼接一个目录

NSString与拓展名

-(NSString*)pathExtension获取拓展名

-(NSString*)stringByDeletingPathExtension删除尾部的拓展名

-(NSString*)strigByAppendingPathExtension在尾部添加一个拓展名

NSString其他用法

-(NSUInteger)length返回字符串的长度

-(unichar)characterAtIndex(NSUInteger)index返回index位置对应的字符

-(double)doubleValue

-(float)floatValue

-(int)intValue

-(char*)UTF8String转换C语言中的字符串

constchar*cs=[stringUTF8String];

NSMutableString

NSString是不可变的,不能删除字符或者添加字符,NSString有一个子类NSMutableString,称为”可变字符串”

创建可变字符串的常用方法

-(id)initWithCapacity:(NSUInteger)capacity

+(id)stringWithCapacity:(NSUInteger)capacity

capacity只是一个最优值,字符串的大小并不仅限于所提供的容量,设置了capacity,可以预分配一块内存来存储它,操作速度快很多

当然,也可以使用创建NSString的方法来创建NSMutableString,因为NSMutableString是NSString的子类,NSMutableString都能使用

NSMutableString*string=[NSMutableStringstringWithFormat:@"ageis%i.",20];

-(void)setString:(NSString*)string初始化完毕后可以使用此方法设置字符串的内容

-(void)appendString:(NSString*)string

-(void)appendFormat:(NSString*)format,...

这两个方法都是在尾部拼接一段字符串

-(void)replaceCharactersInRange:(NSRange)rangeWithString:(NString*)string

将range位置的字符串替换为string

-(void)insertString:(NSString*)stringatIndex:(NSUInteger)loc

在loc这个位置插入string(string的起始位置是loc)

-(void)deleteCharaCharactersInRange:(NSRange)range

删除range这个范围的字符串(经常跟rangeOfString:一起使用删除特定的字符串)

NSArray

用来存储对象的有序列表,它是不是可变的

不能存储C语言中的基本类型,如int、float、enum、struct,也不能存储nil

创建NSArray的常用方法

NSArray*array=[NSArrayarrayWithObjects:...,nil];

NSArray排序

NSArray*sort=[arraysortedArrayUsingSelector:@selector(compere:)];

NSMutableArray

可变数组

NSDictionary

通过唯一的key找到对应的value

NSNumber

NSNumber可以将基本类型包装成对象,这样就可以间接将基本数据类型存进NSArray、NSDictionary等集合中

NSValue

NSMuber是NSValue的子类,但NSNumber只能包装数字类型,NSValue可以包装任意值,也就是可以用NSValue包装结构后加入NSArray、NSDictionary等集合中

NSNull

集合中是不能存放nil值的,因为nil在集合中有特殊含义,但有时确实需要存储一个表示“什么都没有”的值,那么就以使用NSNull,它也是NSObject的一个子类

NSDate的静态初奴化

时间处理

反射

NSString*dogName=@"Dog";

Classclass=NSClassFromString(dogName);

Dog*dog=[[[classalloc]init]autorelease];

NSString*methodName=@"print";

SELmethod=NSSelectorFromString(methodName);

[dogperformSelector:method];

@property(nonatomic,retain)NSString*aString;

property:属性的定义,相当于C语言的setter和getter方法。

assign:简单的赋值,不更改索引的计数。

copy:建议一个索引计数为1的对象,然后释放旧对象;

retain:释放旧对象,将旧对象的值赋予新对象,再增加新对象的索引计数1。

针对具体的数据类型在属性定义应该这样选择:

使用assign:对基础的数据类型,比如NSInterger,CGFloat和C数据类型(int,float,double,char等等)。

使用copy:针对NSString;

使用retain:针对NSObject及其子类。

使用nonatomic:单线程,防止在写未完成的时候被另外一个线程读取,造成数据读取出错。

使用release:基于一般的初始化,使用alloc和init关键词初始化的,要在恰当的地方release掉,全局变量在dealloc方法里面release,常规变量在不需要的时候就要释放掉。

ios关闭键盘的两种方法

[[[UIApplicationsharedApplication]keyWindow]andEditing:YES];

递归找到“叫出”键盘的控件,让它把键盘给退回去

相关推荐