zoukankan      html  css  js  c++  java
  • oc基础知识

    只在@interface中定义变量的话,你所定义的变量只能在当前的类中访问,在其他类中是访问不了的;而用@property声明的变量可以在外部访问。

    用了@property去声明的变量,可以使用“self.变量名”的方式去读写变量。而用@interface的方式就不可以。

    协议与委托 (Protocol and Delegate)

    1 协议:

    协议,类似于Java或C#语言中的接口,它限制了实现类必须拥有哪些方法。
    它是对对象行为的定义,也是对功能的规范。
    示例:

    // GoodChild.h 

    #import <Foundation/Foundation.h> 

    @protocol GoodChild <NSObject> 

    -(void)filialPiety; 

    @end

     

    // Student.h 

    #import <Foundation/Foundation.h> 

    #import "GoodChild.h" //注意实现协议的语法。 @interface Student : NSObject<GoodChild> 

    @end

    // Student.m // protocol // // Created by sxt on 11-10-23. // Copyright 2011年 __MyCompanyName__. All rights reserved. // #import "Student.h" @implementation Student - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)filialPiety{ NSLog(@"孝敬父母。。"); } @end

    此例中定义了一个协议GoodChild,类Student实现了此协议,所以必须有filialPiety方法。
    每个类虽只有一个父类,但可以实现多个协议,以逗号隔开便可。语法如下:

    @interface Student : NSObject<协议1,协议2> @end

     

    2 委托:
    委托是objC中使用非常频繁的一种设计模式,它的实现与协议的使用是分不开的,让我们看一个综合示例:
    小公司老板日常的工作是管理公司、教导新员工、发工资与接电话。
    其中管理公司、教导新员工是老板要亲为的。
    而发工资与接电话老板希望招聘一个秘书来帮忙,于是对秘书的要求就是要略懂出纳发工资,要能帮助领导接电话。 而这两项要求便是协议,对类功能的限定。

     

    // SecProtocol.h #import <Foundation/Foundation.h> @protocol SecProtocol <NSObject> //发工资 -(void)payoff; //接电话 -(void)tel; @end

    然后定义一个秘书类

    // Sec.h #import <Foundation/Foundation.h> #import "SecProtocol.h" @interface Sec : NSObject<SecProtocol> @end

    // Sec.m #import "Sec.h" @implementation Sec - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)payoff{ NSLog(@"sec payoff"); } -(void)tel{ NSLog(@"sec tel"); } @end

    紧接着是老板类:

    // Boss.h #import <Foundation/Foundation.h> #import "SecProtocol.h" @interface Boss : NSObject //此属性用于指定秘书对象,此对象必须实现SecProtocol协议。 @property(nonatomic,retain) id<SecProtocol> detegate; //管理 -(void)manage; //教导新员工 -(void)teach; @end

     

    // Boss.m #import "Boss.h" @implementation Boss @synthesize detegate=_detegate; - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)manage{ NSLog(@"boss manage"); } -(void)teach{ NSLog(@"boss teach"); } -(void)payoff{ NSAutoreleasePool *p=[[NSAutoreleasePool alloc] init]; [_detegate payoff]; [p release]; } -(void)tel{ NSAutoreleasePool *p=[[NSAutoreleasePool alloc] init]; [_detegate tel]; [p release]; } @end

     

    那么老板就具有这4个方法,当调用前2个时是自己完成功能,而调用后2个时则转为调用秘书的方法。
    此时我们跟秘书对象就叫做代理对象,代理模式的名字由来于此。
    最后调用测试下:

    // main.m // delegate // // Created by sxt on 11-10-23. // Copyright 2011年 Jinlong Wei. All rights reserved. // #import <Foundation/Foundation.h> #import "Boss.h" #import "Sec.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //实例化老板对象 Boss *boss=[[[Boss alloc] init] autorelease]; //实例化秘书对象 Sec *sec=[[[Sec alloc] init] autorelease]; //设置老板的代理对象为秘书 boss.detegate=sec; //调用4个方法。 [boss payoff]; [boss tel]; [boss manage]; [boss teach]; [pool drain]; return 0; }

    selector – 选择器

    作者: Jinlong Wei 日期: 2012 年 1 月 21 日没有评论

    在C语言中存在这一种叫做方法指针的东西,这是比较高级的多态特性。 在objC中为了实现类似功能引入了selector ,即选择器。

    选择器的定义方式有两种:

    //第一种 SEL sel1=@selector(haha1); //第二种 SEL sel2=NSSelectorFromString(@"haha2");

    objC中,SEL类型实际为字符串类型,它存储着方法名称。 而C语言中为指针。

    //这里假设存在Person类,且此类有方法为haha Person *p=[[[Person alloc] init] autorelease]; [p haha]; //先判断对象p是否存在sel1的方法,即是否存在名叫haha1的方法 //如果存在调用对象phaha1方法 if ([p respondsToSelector:sel1]) { [p performSelector:sel1]; } //respondsToSelector判断sel2方法是否存在; performSelector调用sel2所代表的方法。 if ([p respondsToSelector:sel2]) { [p performSelector:sel2]; }

    高级应用示例

    //此方法的功能为:调用obj对象的sel方法。 +(void) doMethod:(id)obj meth:(SEL)sel{ if ([obj respondsToSelector:sel]) { [obj performSelector:sel]; }else{ NSLog(@"error"); } }

    Category (分类)

    作者: Jinlong Wei 日期: 2012 年 1 月 12 日没有评论

    前面学过了继承,可以对从父类中得到所有的成员,所谓站在巨人的肩膀上。
    换个角度去看这个问题,继承也是对现有的类进行扩充,这种扩充是纵向的,从父类到子类,再到子类的子类。得到了许多成员,有些是需要的,而有些是多余的。

    在objC中提供了一种叫category的东西,中文一般翻译为“分类”或“类别”。它可以提供类功能的横向扩充。这种扩充有些时候更好用。

    示例:

    // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @end // Person.m #import "Person.h" @implementation Person - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } @end

    // Worker.h #import "Person.h" @interface Worker : Person -(void)doWork; @end // Worker.m #import "Worker.h" @implementation Worker - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)doWork{ NSLog(@"do work.."); } @end

    // WorkerCategory.h #import "Worker.h" //分类,名称要与主类相同,小括号内为分类名称,自行决定名称。 @interface Worker (Category) -(void)strike; @end // WorkerCategory.m #import "WorkerCategory.h" @implementation Worker (Category) -(void)strike{ NSLog(@"我们在罢工!"); } @end

    这个例子中,提供了父类Person,子类Worker,这就是一种典型的纵向扩充-继承。紧接着在WorkerCategory中我们写个一个分类,扩种了一个方法strke。当我们实例化一个Worker对象后可以调用strike方法,这就是一种横向扩展。

    几点说明:
    继承可以得到父类内容,同时可以添加属性和方法。
    而分类只能添加方法,无其他功能。
    横向扩展的分类,给类中添加了新方法,但却不必其他成员。

    从另外一个角度看这个问题,可以将一个复杂的类拆分成多个分类,逐个完成。有利于团队开发和后期维护。并且在使用中,可以根据需要决定import进来哪个分类,而无视不需要的分类。

    示例2:

    // NSDate_Ext.h #import <Foundation/Foundation.h> @interface NSDate (NSDate_Ext) //判断是否是闰年 -(BOOL)isLeapYear; @end // NSDate_Ext.m #import "NSDate_Ext.h" @implementation NSDate (NSDate_Ext) -(BOOL)isLeapYear{ NSDateFormatter *f=[[NSDateFormatter alloc] init]; [f setDateFormat:@"yyyy"]; NSString *year=[f stringFromDate:self]; [f release]; int y= [year intValue]; if ((y%4==0 && y0!=0) || y@0==0) { return YES; }else{ return NO; } } @end // main.m #import <Foundation/Foundation.h> #import "NSDate_Ext.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSDate *now=[[NSDate alloc] init]; NSLog(@"%@",[now isLeapYear]?@"是闰年":@"不是闰年"); [pool drain]; return 0; }

    示例3:

    // NSStringExistNum.h #import <Foundation/Foundation.h> @interface NSString (NSStringExistNum) -(NSUInteger)existNum:(char)c; @end // NSStringExistNum.m #import "NSStringExistNum.h" @implementation NSString (NSStringExistNum) -(NSUInteger)existNum:(char)c{ int num=0; for(int i=0;i<[self length];i++) { char c2= [self characterAtIndex:i]; if (c2==c) { num++; } } return num; } @end // main.m #import <Foundation/Foundation.h> #import "NSStringExistNum.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *s=@"abcdecfg"; NSLog(@"%ld",[s existNum:'c']); [pool drain]; return 0; }

    Objective-C中的面向对象 – 5

    作者: Jinlong Wei 日期: 2012 年 1 月 3 日没有评论

    面向对象的几点补充:

     

    一。实例话对象有的两种办法:

    1 NSObject *o1=[NSObject new];

    2 NSObject *o2=[[NSObject alloc] init];

    实例话出的对象是没区别的,但第二中方法是可以指定构造方法(init)的名称,有利于多态,保证了灵活性,所以后面一律使用第二种方法。

     

    二。每个类只有一个父类,如果不指名默认为NSObject。(继承的单根性)     这点与C++不同。

     

    三。新的“数据类型” id

    作用完全等同于:  NSObject *
    也就是说id是对象指针。

    id a;     等同于     NSObject *b;

     

    objC快速封装 - property

    作者: Jinlong Wei 日期: 2012 年 1 月 3 日没有评论

    objC 2.0中加入了新的特性来实现快速封装。

    前面我们讲过了简单的封装,如果忘记请先复习后接着往下阅读。

    //Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property int age; @property(copy) NSString* name; @end //Person.m #import "Person.h" @implementation Person @synthesize age=myAge; @synthesize name; @end

    两点:
    第一,age=myAge;指定了熟悉名字为myAge,方法名称不变。
    第二,字符串中出现的copy。property()是可以指定多个特性的,常见的有:
    copy:将传递过来的参数复制一份使用。多用于字符串。
    assign:生成基本的封装,此为默认值。
    readwrite:默认,同时可读取可修改。
    readonly:只生成读取方法,不生成set方法,只读。
    retain:set时引用计数加1,涉及到内存管理,后面章节讲解,属性为对象类应该选此项。
    nonatomic:不生成同步块,当不需要多线程访问时应选此项提高执行速度。
    getter:获取器的方法名
    setter:修改器的方法名

    值类型不可以使用以上内容,只有引用类型可用。

     

    伴随着iOS5的发布也引入了ARC特性(后面讲解)加入了两个新关键字:

    weak:用于取代assign
    strong:作用等同于retain,支持ARC

    此部分我建立了专门的章节来讲解此内容。

     

     

    示例:
    @property(nonatomic,readonly) NSString* name;  //生成 name方法,只读。 不使用多线程同步块。

    @property(assign,readwrite,getter = age,setter = setAge:) int age; //生成简单getter和setter方法: 方法名分别叫 age 和 setAge

    @property int age2; //生成 age2 和 setAge2 两个方法。

    @property(nonatomic,copy) NSString *name; //生成无同步块的 name 和 setName 方法 ,其中setName中 name=[_name copy];   (注:_name为参数变量名)

    @property(nonatomic,retain) NSObject *o;  //生成无同步块 o 和 setO 方法,使对象引用计数加1。

     

     

    示例2:

    // Engine.h #import <Foundation/Foundation.h> @interface Engine : NSObject -(void)work; @end

    // Engine.m #import "Engine.h" @implementation Engine - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)work{ NSLog(@"引擎发动。。"); } @end

    // // Car.h #import <Foundation/Foundation.h> #import "Engine.h" @interface Car : NSObject @property(nonatomic,retain) Engine *engine; -(void)drive; @end

    // // Car.m #import "Car.h" @implementation Car @synthesize engine=_engine; - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)drive{ [_engine work]; NSLog(@"小车正常运转。。。"); } -(void) dealloc{ [_engine release]; [super dealloc]; } @end

    Objective-C中的面向对象 – 4

    作者: Jinlong Wei 日期: 2011 年 12 月 30 日没有评论

    多态

    #import <Foundation/Foundation.h> @interface Calc : NSObject -(int)add:(int)a second:(int)b; -(int)add:(int)a second:(int)b third:(int)c; @end

    两个叫add的方法,名称相同,参数不同,此为重载。

    #import <Foundation/Foundation.h> @interface Person : NSObject -(void)faith; @end #import "Worker.h" @implementation Worker - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)faith{ NSLog(@"实现自我价值。"); } @end

    父类Person中包含faith方法和完整功能(部分代码省略),子类中重新编写了faith中的代码。
    此为重写。

    Objective-C中的面向对象 – 3

    作者: Jinlong Wei 日期: 2011 年 12 月 30 日没有评论

    继承

    //Car.h #import <Foundation/Foundation.h> @interface Car : NSObject @property int age; @property(copy) NSString *color; -(void)drive:(int) s; -(void)turn:(int)s second:(double) t; -(void)stop; //静态方法 +(void)helloWorld; @end //Car.m #import "Car.h" @implementation Car @synthesize age=_age; @synthesize color; +(void)helloWorld{ NSLog(@"hello objC"); } //构造,在实例化对象时自动执行。 - (id)init { self = [super init]; if (self) { // Initialization code here. NSLog(@"car闪亮登场"); } return self; } //析构,在删除对象时自动执行。 - (void)dealloc{ NSLog(@"car 结束了他的生命"); } -(void)drive:(int) s{ } -(void)turn:(int)s second:(double) t{ } -(void)stop{ } @end

    以上为类Car

    //BMW.h #import "Car.h" @interface BMW : Car -(void) zhuangX; @end //BMW.m #import "BMW.h" @implementation BMW - (id)init { self = [super init]; if (self) { // Initialization code here. NSLog(@"bmw 闪亮登场"); } return self; } - (void)dealloc{ NSLog(@"bmw 结束了他的声明"); } -(void) zhuangX{ NSLog(@"帅的。。。 "); } @end

    objC中继承使用:关键字。无特别之处。
    类的内部用self指代自身(相当于Java中的this)
    用super指代父类对象。

    Objective-C中的面向对象 – 2

    作者: Jinlong Wei 日期: 2011 年 12 月 30 日没有评论

    首先扯一个和OOP关系不大的问题,方法的参数。

    //一个参数时,参数类型写在括号中。
    -(void)run:(int) l;

    //两个参数时,第二个参数需要有名字(at就是名字),而day是变量名,请勿搞混。
    -(void)run:(int)l at:(NSString*) day;

    用法:[self run:5 at:@"今天"]; //at名称必须在,而“今天” 赋值给了变量day
    注解:objC中调用方法的形式比较特别,此段代码等效于Java中的: this.run(5,”今天”);

    //多个参数时
    -(NSInteger)add:(int)a second:(int)b third:(int)c;
    用法:[self add:1 second:2 third:3];
    道理同上,第二个参数开始必须有。

    好,第二个问题,封装的高级写法。没人希望用大量的时间写大量的封装代码,太锻炼身体了,objC2.0中提供了新的特性来解决这个问题。

    //Person.h #import <Foundation/Foundation.h> @interface Person : NSObject{ int age; } -(int)age; -(void)setAge:(int)_age; @end //Person.m #import "Person.h" @implementation Person -(int)age{ return age; } -(void)setAge:(int)_age{ age=_age; } @end

    这是一个简单封装的例子,此段代码等效于:

    //Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property int age; @end //Person.m #import "Person.h" @implementation Person @synthesize age; @end

    代码中:
    @property int age;声明了age进行封装。
    @synthesize age;指定实现age的封装。

    通过两个关键字简单的实现了同样的功能。
    此时将生成一个用于读取的age方法,和一个用于修改的setAge方法。
    属性名为:age

    关于@proterty的详细内容稍后章节讲解。

    Objective-C中的面向对象 – 1

    作者: Jinlong Wei 日期: 2011 年 12 月 30 日没有评论

    面向对象是计算机编程中非常重要的思想,毫无疑问objC是完全支持OOP(面向对象编程)。
    此文假设你有OO思想,话句话说着这不是一篇OOP入门文章,而是在讲解objC中如何体现OOP思想。

    定义一个类。

    //Pen.h #import <Foundation/Foundation.h> //类名称为Pen , 继承自父类NSObject @interface Pen : NSObject //定义一个方法,无返回值,名称叫write //减号表示是个实例方法 ,加号表示是个静态方法 -(void)write; @end //Pen.m #import "Pen.h" @implementation Pen 此方法为objC类的构造方法 - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } //方法的实现,显示一行文字。 -(void)write{ NSLog(@"write...."); } @end

    objC中每个类由2个文件组成,.h文件和.m文件。 这非常类似于C++的做法。
    当然,只有一个.h文件也可以写出一个完整的类。但通常我们将类的声明部分放在.h头文件中,而将方法的实现写在.m文件中
    NSObject为所有类的父类。
    init为类的构造方法。在此方法中首先调用[super init]来构造出父类对象,然后判断是否成功,if语句中可以写你想在构造时所作的初始化工作。self中存放这对象的内存首地址。

    实例化一个对象的两种方法:
    Pen *p1=[[Pen alloc] init];
    Pen *p2=[Pen new];

    两种等效,但推荐第一种。 代码虽麻烦,但可以指定调用叫init的构造,便于实现多态,灵活性的体现。

    alloc关键字的作用为申请内存空间

    调用write方法:
    [p1 write];

    多数编程语言中喜欢使用 p1.write();这样的写法,objC中非常另类,开始可能写的不习惯,当配合xcode写顺手了之后非常好用。

    看个复杂的:

    [[[Person alloc] init] sleep];
    先实例化一个Person类的对象,然后调用sleep方法,你看懂了么?

    属性和封装的例子

    //Person.h #import <Foundation/Foundation.h> @interface Person : NSObject{ NSString *name; @public int age; @private int height; } -(NSString*)name; -(void)setName:(NSString*)_name; -(void)sleep; @end //Person.m #import "Person.h" @implementation Person -(NSString*)name{ return name; } -(void)setName:(NSString*)_name{ name=_name; } -(void)sleep { NSLog(@"huhu..."); } @end

    此例中,对象Person有3个属性:name,age,height。 name为protected (即默认为name为protected);age为public ;height为private。

    紧接着我为name属性做了个封装 ,于是有了两个方法:name和setName ,objC中不喜欢把方法命名为getName,而是直接叫name,不要和属性name搞混。

    在setName方法中,冒号后面的为参数,类型为NSString* ,即字符串指针,变量名叫_name。

    Objective-C语法基础 – 3

    作者: Jinlong Wei 日期: 2011 年 12 月 29 日没有评论

    int a=5; //C语言一样,非0表示真 if (a) //结果为真 { NSLog(@"hahaha"); } //C语言中的布尔型本质上是整数 bool b=true; if(b) //结果为真 { NSLog(@"hoho"); } //objC中的布尔型变量,本质上为unsigned char //iOS开发中多采用BOOL,注意大小写 BOOL b=TRUE; if (b) //结果为真 { NSLog(@"12312312"); } C语言中的sizeof()一样,可以显示出占用内存的大小(字节数) NSLog(@"%ld",sizeof(5)); int a=34; NSLog(@"%ld",sizeof(a)); NSLog(@"%ld",sizeof(NSInteger)); int a[]={1,2,3,4,5}; //数组占用的内存大小为每个变量的大小乘以数组长度 int n=sizeof(a); //除以5得到每个int的大小。 n=n/5; NSLog(@"%d",n);

     

    最后一个小知识:

    typedef long NSInteger;

    看出来了吧,NSInteger类型就是长整数,这在iOS开发中时常出现。

     

     

  • 相关阅读:
    C# EPPlus 导出Excel
    NetCore +EF+Mysql 从数据库生成实体类到项目
    VBA链接SQL server数据库
    sqlserver中的 binary varbinary image
    sql server DateTime与DateTime2的区别
    Sql Server增删改查字段的语法
    c#中queue的用法
    Sql Server中不相关的两个数据表的全部显示
    IActionResult的返回值类型
    linux内存映射
  • 原文地址:https://www.cnblogs.com/cainiaoaixuexi/p/3607687.html
Copyright © 2011-2022 走看看