《Objective-C程序设计》学习笔记——语法篇


Terminal编译OC代码的指令:

mkdir test01
cd test01
vi main.m
clang -fobjc-arc -framework Foundation main.m -o test01
./test01
@autoreleasepool{ 
    NSLog(@"Program is running!");
}

@autoreleasepool:应用创建新对象时,系统能够有效的管理应用使用的内存
NSLog:

  1. 后面参数中的@"...."成为常量NSString对象,如果不加@,就是常量C类型的字符串
  2. NSLog函数会输出函数的执行日期与实践、程序名、以及其他一些数值
创建类和对象的方式:(分数程序-分子/分母)
//
//  main.m
//  OC-Test01
//
//  Created by 修宇亮 on 14-7-22.
//  Copyright (c) 2014年 修宇亮. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Fraction : NSObject

-(void) setNumeration : (int) n;
-(void) setDenomination : (int) d;
-(int) numeration;
-(int) denomination;
-(void) print ;

@end

@implementation Fraction

{   int Numeration;
    int Denomination;
}
//声明变量最好在@implementaion,这样可以保证数据的封装性
//如果只声明一行数据,可以不用大括号

-(void) setNumeration:(int)n
{
    Numeration = n;

}

-(void) setDenomination:(int)d
{
    Denomination = d;
}

-(int) numeration{

    return Numeration;
}

-(int) denomination{

    return Denomination;
}

-(void)print
{
    NSLog(@"The fraction is %i / %i",Numeration,Denomination);
}
@end


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

    @autoreleasepool {

        Fraction *frac1 = [[Fraction alloc]init];
        Fraction *frac2 = [[Fraction alloc]init];
        //另一种写法:Fraction *frac1 = [Fraction new];
        //但建议用第一种方法书写,因为这样可以更加容易的理解“先分配内存空间,再初始化对象”这个过程

        [frac1 setNumeration : 2];
        [frac1 setDenomination:3];


        [frac2 setNumeration : 2];
        [frac2 setDenomination:7];

        [frac1 print];
        [frac2 print];
        //另一种写法:
        //NSLog(@"The fraction is %i / %i",[frac1 numeration],[frac1 denomination]);
        //体现了每个对象中数据的封装性,外界只有通过创建对象或者访问已有对象,才能获得该对象的数据


    }
    return 0;
}
数据类型和表达式
NSLog转换字符:
int char float double id
%i %c %f,%e,%g,%a %f,%e,%g,%a %p

%f是指用浮点数的形式输出,也就是用小数了
%e是用指数的形式输出
%g是选用%f%e中较短的一种形式输出

浮点数科学计数法:

1.7e4 = 1.7*10^4

限定词:

long:修饰int,double,float,以扩大值域,可以连续运用,如long long int
short:与long的效果相反,可以起到节约内存的作用
unsigned:只有正值,没有负值,从而扩大正值的值域
id:通用类型,id object,在多态和动态绑定中有重要作用

模运算符
NSLog(@"a%%b = %i",a%b);
//当需要在输出的字符串中加入%时,需要用%%,%相当于java中的\转义符
//%是取模运算,得到的结果是余数
//如果数据类型是int,那么/运算的结果是整数,小数部分被砍掉了
//a/b+a%b = a
类型强制转换

15/10 = 1
(float)15/10 = 1.5000
(float)15/(float)10 = 1.5000

id object;
Fraction *myfraction;
myfraction = (Fraction *) object;//将id强制类型转换为Fraction *
键盘输入
scan("%i",&number);//这里不需要@,这里是C语法,不是NSString类型参量
scan(" %c",char);//注意,这里%c之前有一个空格,功能是自动跳过空白字符(空格,回车,换                 //行符,制表符),需要从键盘输入单个字符的时候要尤其注意这一点
break & continue

break:跳出循环,从循环后面的语句执行
continue:跳出正在执行的本次循环,从下一次循环开始执行,但仍旧在循环之内运行

关于类:
工程中文件的分布:

一般在写项目的时候
interface和implementation是分开在两个文件里面写的
class.h和class.m
其中class.m需要导入class.h
而main.m也需要导入class.h,但不需要导入class.m
这种文件分配,很有利于大量代码的管理

自动生成取值、设值方法
@interface
@property int a,b;
@end
-----------------
@implementation
@synthesize a,b;
@end
使用点运算符访问属性
object.property == [object property]
//点运算符多用于取值设值的时候,如果是单纯调用方法,还是推荐用[]
具有多个参数的方法
@interface
-(void) setTo : (int) n over : (int) m
@end
---------------------
@implementation
-(void) setTo : (int) n over : (int) m
{
    numeration = n;
    denomination = m;
}
@end
----------------------
main.m
[object setTo :1 over :3];
----------------------
求最大公约数
-(void) reduce : (Fraction *) f 
{
    int u = f.numeration;
    int v = f.denomination;
    int temp;

    while(temp!=0)
    {
        temp = u%v;
        u = v;
        v= temp
    }

    f.numeration \= u;
    f.denomination \= u;
}
关键字

static:
累加器,在方法中修饰局部变量可以使得局部变量可以实现累加功能,不会因为每次重新初始化而使得局部变量“归零”

self:

-(void) add : (Fraction *) f
{
    //a/b+c/d = (a*d+c*b)/b*d

    numeration = f.numeration*denomination+f.denomination*numeration;
    denomination = denomination*f.denomination;

    [self reduce];//直接对得到的结果进行约简,相当于java的this
}
关于继承

详情见代码包——Rectangle
main.m(import "XYPoint.h"&&"Rectangle.h")
XYPoint.h
XYPoint.m(import "XYPoint.h")
Rectangle.h
Rectangle.m(import "Rectangle.h")

@class
#import <Foundation/Foundation.h>

@class XYPoint;
//声明,如果下面出现XYPoint字样,说明要使用XYPoint类,相当于一个类名称标记
//也可以换成#import "XYPoint.h",但这个样子需要导入和处理整个XYPoint文件,
//但如果需要调用XYPoint类的方法和参数,则需要导入完整的XXPoint.h文件
//需要放在@interface之前声明,不能放在之后

@interface Rectangle : NSObject
@property int width,height;

-(int) area;
-(int) perimeter;
-(XYPoint *) origin;
-(void) setWidth : (int) w andHeight : (int) h;
-(void) setOrigin : (XYPoint *) pt;


@end
有关类的问题
if ([com1 isMemberOfClass :[Complex class]] == YES) ;//对象是不是该类的成员
if ([com1 isKindOfClass :[NSObject class]] == YES) ;//对象是不是该类或者该类子类的成员

if ([com1 respendsToSelector :@selector (setReal:andIma:)] == YES) ;//对象能不能响应这个方法
if ([Complex instancesRespendToSelector :@selector (setReal:)] == YES) ;//该类能不能响应这个方法
if ([Complex isSubclassOfClass :[NSObject class]] == YES) ;//该类是不是后面类的子类
有关异常处理

    @try 
    {
        int b = 0; 
        switch (b)  
        {
            case 0:
                @throw(ex);//b=0,则抛出异常;
                break;
            default:
                break;
        }
    }
    @catch (NSException *exception)//捕获抛出的异常 
    {
        NSLog(@"b==0 Exception!");
    }
    @finally 
    {
        NSLog(@"finally!");
    }
    [ex release];
}
//运行的结果:
b==0 Exception!
finally!
重写对象的初始函数
-(Fraction *) initWith :(int) n over: (int) d
{
    self = [super init];

    if(self)
    {
        [self setTo :n over :d];
    }

    return self;
}

-(void) setTo :(int) n1 over :(int) d1
{
    self.Numeration = n1;
    self.Denomination = d1;
}

//这里之所以使用id的返回值,是为了给后续对init的继承做准备,因为后续需要对init继承的时候,子类的类名和父类是不相同的,因此用id可以规避掉因为类名改变而不断变化返回值类型的麻烦

-(id) init 
{
    return [self initWith :0 over:0];
}

执行语句

Fraction *frac1 = [[Fraction alloc]initWith :4 over :6];
实例变量作用域

@protected : 可被本类及子类访问,interface中定义的变量默认为这种类型

@private : 仅能被本类的方法访问,implementation中定义的变量默认为是这种类型

@public : 哪都可以用

@package : 本类的映像的任何敌方都可以访问这个变量

@synthesize windown = _windown;
//windown是类的属性,而_windown是具体的类属性的实例变量

[windown makeKey];//没法运行
[_windown makeKey];//可以运行
[self.windown makeKey];//可以运行
extern
  1. 如果class A的变量 x 需要被好多个class使用:

那么在classA中把x定义成:

extern int x;
x = 100;

使用该变量的类,可以直接:

int x;
  1. 如果class A中的变量虽然会被其他class用,但是用的不多:

那么class A中把x定义成:

int x = 100;

使用该变量的类,可以引用为:

extern int x;
 x = 200;
类函数和成员函数
//类函数:可以直接用类名调用,不能有成员变量
Fraction *fraction = [[Fraction allocF]init];

+(Fraction *) init;
+(Fraction *) allocF;

//成员函数:必须通过对象调用
Fraction *fraciton = [[Fraction allocF]init];
fraction.count = 1;
[fraction add :3 over :4];

-(int) count;
-(void) add :(int) n over(int) m;

-----------------------------------------

static int counter;

+(Fraction *) allocF
{
    extern int counter;
    counter++;

    return [Fraction alloc];

}

+(int) count
{
    extern int counter;
    return counter;
}
枚举语法和typedef重命名
//声明enum
enum Direction{north=1,south,east,west};//1,2,3,4
enum Direction{north,south,east,west};//0,1,2,3
//定义enum对象
enum Direction direction1;
direction1 = (enum Direction) 3;
//免enum名,定义enum对象
enum{north,south,east,west} direction2;
//typedef重命名enum
typedef enum {north,south,east,west} Direction;
Direction direction3,direction4;

//typedef的作用主要是,为一些数据类型起一个“小名”,以方便程序的阅读,比如你写一个int定义x,大家不知道什么意思,但是你写Counter定义一个x,大家就知道,这个x其实是一个计数器

typedef int Counter;
//这两条定义语句功能相同
int x = 1;
Counter x =1;
分类与类的扩展
//Fraction.m
#import "Fraction.h"

//分类MathOps,在Fraction.m里面一起实现
//不必列出父类和实例变量,因为这些已经包括在Fraction.h

@interface Fraction(MathOps)

-(Fraction *) reduce :(Fraction *) f; 
-(Fraction *) multiple :(Fraction *) f; 
-(Fraction *) divide :(Fraction *) f; 

@end

@implementation Fraction(MathOps)
-(Fraction *) reduce :(Fraction *) f
{
    ......
}

@end
类的扩展/未命名分类
@interface Fraction()
//括号里面没有命名
//可以定义实例变量来扩展类,这个是相比于命名分类的一个优势,命名分类不能定义实例变量
//定义的扩展方法必须在主实现区域内实现,否则会编译报错
@property int UniqueID;
-(Fraction *) square :(Fraction *) f; 

@end

@implementation Fraction(MathOps)

@syntheasize UniqueID;
-(Fraction *) square :(Fraction *) f
{

}

@end
协议与代理(协议实现的过程代理给继承他的子类)

声明一组协议

NSObject.h

@protocol NSCopying

-(id)copyWithZone :(NSZone *)zone;

@end

实现一组协议

@interface AddressBook :NSObject<NSCopying,NSCoding>
//虽然不需要定义协议包含的接口,但必须在下面进行实现

可选择协议与死规定协议

//协议都是父类定义,子类实现
@protocol Drawing//死规定协议,继承的子类必须实现
-(void) paint;
-(void) erase;
@optional//可选择协议,继承的子类可实现可不实现
-(void) outline;
@end

检察一个对象是否遵循Drawing协议

if([currentObject conformsToProtocol : @protocol (Drawing)] == YES)
//同类概念——检查一个类是否实现了一个方法
if ([Complex instancesRespendToSelector :@selector (setReal:)] == YES) ;

检察一个对象是否实现了Drawing 协议中的outline方法

if([currentObject respondsToSelector : @selector (outline) == YES])

检察变量的协议一致性

id<Drawing> currentObject;

扩展现有的协议

@protocol Drawing3D(Drawing)

分类也可以实现一组协议

@interface Fraction (stuff)<NSCopying,NSCoding>
合成对象

square是Rectangle类的子类,是父子继承关系,但是Rectangle里面的很多方法并不适用于square,如果只单纯继承,会继承很多无用的方法,因此用下面的代码可以直接新定义一个类,这个类有很多新定义的属于自己的方法,这个方法和分类、子类都是扩展类定义的一种方法

//@interface square:Rectangle 这是原来的方法

@interface square :NSObject
{
    Rectangle *rect;
}

-(int) size;
-(int) setsize: (int) s;
-(int) area;
-(int) perimeter;

@end

@implementation square
-(void) area
{
    return [rect area];//使用父类方法的方式
}
@end

------------
//但是这种方法在初始化的时候需要为square和rectangle都预留一部分地方
//因此要重写init或者添加initWithSide之类的新方法来分配空间
预处理

预处理语句可以放在任何位置,但是大多数程序员把定义放在头文件,以便在多个源文件中引用
定义的变量和方法一般都用大写

#define:名称置换(相当于word中的替换,所以不能加;这样分号也就替换进去了)+宏方法定义

#define TRUE 1
#define PI 3.1415926
#define TWO_PI 2.0*PI
#define AND &&
if(time AND place) ==if(time && place)
#define OR ||
if(time OR place) ==if(time || place)

#define IS_LEAP_YEAR year%4 ==0&&year%100 !=0\
||year%400 ==0      \是为了提示编译器还有一个后续
if(IS_LEAP_YEAR).....

//这样就不局限与当前year变量,而是普遍适用于任意年
#define IS_LEAP_YEAR(y) y%4 ==0&&y%100 !=0||y%400 ==0    
if(IS_LEAP_YEAR(y)).....

#define SQUARE(X) ((X)*(X))
//如果不加括号,会导致v+1*v+1,加了括号就是(V+1)*(V+1)

#define MakeFraction(x,y) ([[Fraction alloc]initWith: x over :y])
myFract = MakeFraction(1,3);
#define MAX(a,b) ((a)>(b)?(a):(b))
//用括号括起来,是为了避免运算错误
//1.MAX(x+1,y)*100  2.MAX(x&y,z)

#define IS_LOWER_CASE(x) (((x)>('a'))&&(x)<('z'))//返回真值
#define TO_UPPER(x) (IS_LOWER_CASE(x)? ((x)-'a'+'A'):(x))//返回字母
#define IPAD 1

#ifdef IPAD
#   define IMAGE @"ipad.jpg"//别忘了空格
#elif IPHONE//#else
#   define IMAGE @"iphone.jpg"//别忘了空格
#endif

编译过程中,可以通过 -D IPAD 来声明IPAD,从而是所有出现#ifdef IPAD的地方都通过
Xcode在Buildsetting中设定 IPAD DEBUG
gcc -framework-Foundation -D IPAD main.m -
#if defined(DEBUG)
NSLog(@"usename = %s,userid = %i",Username,UserId);
#elif......
#endif
//功能等价于
#ifdef DEBUG
NSLog(@"usename = %s,userid = %i",Username,UserId);
#elif......
#endif

//要保证DEBUG不仅仅被定义而且值非零才能继续进行下一步
#if defined(DEBUG)&&DEBUG
#define.....
//消除定义
#undef IPAD
之后的#ifdef IPAD和#if defined(IPAD)两句话的值都是false

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值