`

Objective-C初探

    博客分类:
  • ios
阅读更多
Objective-C简介(简称OC)
基于C语言,增加了最小的面向对象语法,完全兼容C语言
Mac OS X和 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

OC 2.0中引入的新关键字有
@property,@synthesize
@optional,@required,@dynamic

OC语法纵览2
基本数据类型 int、float、double、char、Bool(YES/NO)等
id类型       每个对象都可以表达为id类型,可以认为是NSObject*或者void*
nil           等同于NULL
基本语法     循环语句(do while、while、for)、条件语句(if、if else、switch)、Boolean(YES NO)、条件运算符、goto语句、空语句、逗号表达式、sizeof运算符、命令行参数、位操作都和C一样
for循环扩展  for(xx in xx)
基类         NSObject
继承         单继承
多态         支持多态
抽象类       支持抽象类
异常处理     @try @catch @finally
日志输出     NSLog(@"Hello World"); NSLog(@"My age is %i",25);
注释         /*......*/ 和 //

OC语法纵览3
OC提供了BOOL类型,但是这个Bool类型和C++里的并不一样;在C++里一切非0值的东西都为true,而为0值为false,但在OC里1为true并被宏定义为YES,0为false并被宏定义为NO
所以,下面的代码,肯定是错误的:
Bool areDifferent(int a,int b)
{
   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框架,用于开发Mac OSX平台的应用程序
Cocoa框架在iOS上叫做Cocoa Touch,包含两个核心框架:Foundation框架和UIKit框架,用于开发iOS平台的应用程序(iPhone\iPod\iPad)
Cocoa Touch与Cocoa一个比较鲜明的区别就是Cocoa Touch并不支持垃圾回收机制,这就意味着你必须在你的代码里管理好你的内存

常用拓展名
拓展名     含义
.h       头文件。用于描述类的组件,包含成员变量、成员方法、类变量、类方法
.c       c源文件
.cpp .cc c源文件
.m       objective-c源文件,也叫实现类的类文件,可以包含Objective-C和C代码,一般一个.m文件会和一个.h相对应。
.mm      objective-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 = [Student alloc];
调用构造方法,初始化对象
[stu init];
销毁对象
[stu release];

一般来说创建和初始化连着一起操作
Student *stu = [[Student alloc] init];
/*...........................*/
[stu release];

构造方法
-(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 = [[CLStudent alloc] init];
NSObject *obj = [CLStudent new];

注释
#pragma mark - getter  注释一类方法
#pragma mark 设置年龄  单个方法注释
也可以安装额外的服务生成Doxygen文档注释

点语法(调用是set/get方法)
student2.age=10;
NSLog(@"age is %i,no is %i",student2.age,student2.no);

@property作用
@property int age;   自动声明set/get方法
-(int) age;  //int getAge()
-(void)setAge:(int) _age; //getAget(int age);
@property(readwrite,getter = getID) int age;
@property(readwrite,atomic,retain) int age;

@synthesize作用
@synthesize age;   自动生成实现set/get方法

内存管理
范围
任何继承了NSObject的对象,对基本数据类型无效
原理
每个对象内部都保存了一个与之相关的整数,称为引用计数器
当使用alloc、new或者copy创建一个对象时,对象的引用计数器被设置为1
给对象发送一条retain消息,可以使引用计数器值+1
给对象发送一条releain消息,可以使引用计数器值-1
当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收,OC也会自动向对象发送一条dealloc消息,一销毁会重写dealloc方法,在这里释放相关资源,一定不要直接调用dealloc方法
可以给对象发送retainCount消息获得当前的引用计数器值

@class
在申明时使用@class
在使用时使用#import
assign 直接赋值

自动释放池(autorelease pool)
自动释放池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和OS X开发中,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的定义
typedef struct _NSRange{
    NSUInteger location;
    NSUInteger length;
} NSRange;
// typedef unsigned long NSRange;
这个结构体用来表示事物的一个范围,通常是字符串里的字符范围或者集合里的元素范围
location表示该范围的其实位置
length表示该范围内所含元素个数
比如"I love objective-c"中的"obj"可以用location为7,length为3的范围来表示
NSRange
有3种方式创建一个NSRange变量
第1种:直接给成员赋值
NSRange range;
range.location = 7;
range.length = 3;
第2种:应用C语言的聚合结构赋值机制
NSRange range = (7,3);
或者NSRange range = {.location = 7,.length = 3);
第3种:Foundation框架提供的一个快捷函数NSMakeRange
NSRage range = NSMakeRange(7,3);

NSRange range ={.location=1,.length=3};
NSRange range = NSMakeRange(3,4);
NSLog(@"location:%zi,length:%zi",range.location,range.length);

NSPoint
在Foundation/NSGeometry.h中对NSPoint的定义
typedef CGPoint/CGGeometry.h中对CGpoint的相关定义
struct CGPoint{
  CGFloat x;
  CGFloat y;
}
typedef struct CGPoint CGPoint
// #define CGFLOAT_TYPE double
// typedef CGFLOAT_TYPE CGFloat;
NSPoint和CGPoint是等价的
这个结构体代表的平面中的一个点(x,y)
CGPoint point = NSMakePoint(10,20); //==NSPoint point = NSMakePoint(10,20);
NSLog(@"x:%.0f,y:%.0f",point.x,point.y); //.表示小数个数
// 等价 CGPointMake(10,20);

NSSize
在Foundation/NSGeometry.h中对NSSizer的定义
typedef CGSize NSSize;
在CoreGraphics/CGGeometry.h中对CGSize的相关定义
struct CGSize{
   CGFloat width;
   CGFloat height;
};
typedef struct CGSize;
这个结构体用来存储宽度和高度
可以利用NSMakeSize()和CGSizeMake()创建CGSize

NSRect
在foundation/NSGeometry.h中对NSRect的定义
typedef CGRect NSRect;
在CoreGraphics/CGGeometry.h中对CGRect的相关定义
struct CGRect{
   CGPoint origin;
   CGSize size;
}
typedef struct CGRect CGRect;
这个结构体用来存储宽度和高度
可以利用NSMakeRect()和CGRectMake()创建CGRect

NSString的创建
创建常量字符
NSString *string = @"This is a String!";
创建空字符串,给予赋值
NSString *string = [[NSString alloc] init];
string = @"This is a String";
通过字符串创建字符
[[NSString alloc] initWithString:@"This is a String!"];
//或者 [[NSString alloc] initWithFormat:@"My age is %i",20];
NSString *string = [NSString stringWithFormat:@"My age is %i",20];
用标准C创建字符
char *cString = "这是一串中文";
[[NSString alloc] initWithCString:cString ancoding:NSUTF8StringEncoding];
或者 [[NSString alloc] initWithUTF8String:cString];
//字符串编码可以在NSString.h中查阅

从文件中读取
NSString *path = @"/Users/apple/Desktop/test.txt";
NSStringEncoding enc =CFStringConvertEncodeingToNSStringEncoding(KCFStringEncodingGB_18030_2000);
NSError *error = nil;
NSString *string [[NSString alloc] initWithContentsOfFile:path encoding:enc error:&error];//&error 指针地址--指向指针的指针
if(error != nil){
   NSLog(@"\n读取错误,错误信息:\n%@",[error localizedDescription]);
}
[string release];

从远程文件读取
NSError *error = nil;
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];  //NSURL *url = [NSURL URLWithString:@"file:///Users/apple/Desktop/test.txt"];
NSString *string = [[NSString alloc] initWithContentsOfURL:url,encoding:NSUTF8StringEncoding,error:&error];

NSString 文件导出
NSString *string = @"123456";
NSString *path = @"/Users/apple/Desktop/123.txt";
[string writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
[string writeToURL:...] //写到远程

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 *)uppercaseString string全部转为大写
-(NSString *)lowercaseString string全部转为小写
-(NSString *)capitalizeString string首字母变大写,其它字母都小写

NSString 的搜索
-(BooL)hasPrefix:(NSString *) string 是否以string开头
-(BooL)hassuffix:(NSString *) string  是否以string结尾
-(NSRange)rangeOfString:(NSString *)string 检查是否包含了atring,如果包含,返回string位置,如果不包含的location为-1,length为0
-(NSRange)rangeOfString:(NSString *)string options:(NSStringCompareOptions) mask 可以传递一个mask参数,改变搜索方式 
比如NSStringCompareOptions为NSBackwardsSearch表示从尾部开始搜索
-(NSRange)rangeOfString:(NSString *)string options:(NSStringCompareOptions)mask range:(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语言中的字符串
const char *cs = [string UTF8String];

NSMutableString
NSString是不可变的,不能删除字符或者添加字符,NSString有一个子类NSMutableString,称为”可变字符串”
创建可变字符串的常用方法
-(id)initWithCapacity:(NSUInteger)capacity
+(id)stringWithCapacity:(NSUInteger)capacity
capacity只是一个最优值,字符串的大小并不仅限于所提供的容量,设置了capacity,可以预分配一块内存来存储它,操作速度快很多
当然,也可以使用创建NSString的方法来创建NSMutableString,因为NSMutableString是NSString的子类,NSMutableString都能使用
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i.",20];
-(void)setString:(NSString *)string 初始化完毕后可以使用此方法设置字符串的内容
-(void)appendString:(NSString *)string
-(void)appendFormat:(NSString *)format,...
这两个方法都是在尾部拼接一段字符串
-(void)replaceCharactersInRange:(NSRange)range WithString:(NString *)string
将range位置的字符串替换为string
-(void)insertString:(NSString *)string atIndex:(NSUInteger)loc
在loc这个位置插入string(string的起始位置是loc)
-(void)deleteCharaCharactersInRange:(NSRange)range
删除range这个范围的字符串(经常跟rangeOfString:一起使用删除特定的字符串)

NSArray
用来存储对象的有序列表,它是不是可变的
不能存储C语言中的基本类型,如int、float、enum、struct,也不能存储nil
创建NSArray的常用方法
NSArray *array = [NSArray arrayWithObjects:...,nil];

NSArray排序
NSArray * sort = [array sortedArrayUsingSelector:@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";
Class class = NSClassFromString(dogName);
Dog *dog = [[[class alloc] init] autorelease];
NSString *methodName = @"print";
SEL method = NSSelectorFromString(methodName);
[dog performSelector: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关闭键盘的两种方法
[[[UIApplication sharedApplication] keyWindow] andEditing:YES];
递归找到“叫出”键盘的控件,让它把键盘给退回去
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics