OC学习_10_异常_包装类

本文介绍了Objective-C中的自动引用计数(ARC)机制及对象指针修饰符,并详细探讨了异常处理的概念、语法结构、执行流程及自定义异常的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

======文档更新状态=====
2015-12-24:发布

==================

day10-[2015-12-23]
一、关于ARC的补充
1.和属性修饰符对应的有3个对象指针修饰符,均以2个下划线开头,再加上相应的属性修饰符名称
2.在ARC中,将一个对象指针赋给另一个对象指针,默认采用__strong方式(相当于MRC下调用retain方法),可以指定__weak、__unsafe_unretained(相当于MRC下直接赋值)

//  YYBook.h

#import <Foundation/Foundation.h>

@interface YYBook : NSObject
@property (nonatomic,copy)NSString* title;
@property (nonatomic,assign)int price;
-(instancetype)initWithTitle:(NSString*)title price:(int)price;
@end
//  YYBook.m

#import "YYBook.h"

@implementation YYBook
-(instancetype)initWithTitle:(NSString *)title price:(int)price{
    if (self=[super init]) {
        self.title=title;
        self.price=price;
    }
    return self;
}
-(void)dealloc{
    NSLog(@"Book %@ dealloc",_title);
}

-(NSString *)description{
    return [NSString stringWithFormat:@"Book %@ %d",_title,_price];
}
@end
//  main.m

#import "YYBook.h"
//main函数本身就是一个最大的ARP
int main_arc(int argc, const char * argv[]) {
    //__strong、 __weak、 __unsafe_unretained
    __weak YYBook* bk2=nil;
    @autoreleasepool {
        YYBook* bk=[[YYBook alloc]initWithTitle:@"iOS" price:20];
        bk2=bk;
        NSLog(@"bk:%@",bk);
    }
    NSLog(@"bk2:%@",bk2);
    NSLog(@"end of main.");
    return 0;
}
执行结果:
2015-12-24 00:13:21.775 1223[2255:96860] bk:Book iOS 20
2015-12-24 00:13:21.777 1223[2255:96860] Book iOS dealloc
2015-12-24 00:13:21.778 1223[2255:96860] bk2:(null)
2015-12-24 00:13:21.778 1223[2255:96860] end of main.

二、异常Exception
1.概念:运行时错误,一般由运行环境造成,有别于主观原因造成的语法、算法错误
2.语法结构:@try{
//有可能产生异常的代码
}@catch(异常类型指针){
//产生异常时的处理代码
}@finally{
//不管是否有异常产生都有执行的代码
}
3.执行流程:try块中一旦有代码产生异常,则该行及其后的代码都不再执行,转到catch块中执行,执行完后进入finally块执行,执行完后如果还有代码则继续执行;try块中全部代码都没有产生异常,则跳过catch直接进入finally块执行,执行完后如果还有代码则继续执行;finally权限较高,即使在try或catch中有return,也必须等finally执行完才能返回,除非强制退出exit(0)函数;所以不建议在finally中有return语句
4.抛出异常@throw的用法,在需要抛出异常的方法或函数中使用该指令,后面跟上一个NSException对象(可以使用规范的类方法或初始化方法)
5.自定义异常
A.定义NSException的子类
B.根据需要定义、重写相关方法
C.抛出自定义异常和抛出NSException相同
D.捕捉:注意顺序(父子层次关系越低的越靠前,NSException肯定写在最后)
6.OC的异常处理机制不适用于C的函数,但可以通过其他方式来辅助判断是否出现异常

//  YYDemo.h

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

@interface YYDemo : NSObject
@property (nonatomic,assign)int price;
@property (nonatomic,assign)int age;
-(void)method1;
-(void)method2;
@end
//  YYDemo.m

#import "YYDemo.h"


@implementation YYDemo
-(void)method1{
    NSLog(@"Method1 in YYDemo");
}
/**
 *  如果参数为负数,抛出reason为价格偏低的信息
 *  如果参数大于1000,抛出reason为价格偏高的信息
 *
 *  @param price
 */
-(void)setPrice:(int)price{
    if (price < 0){
        @throw [NSException exceptionWithName:@"价格异常" reason:@"价格偏低" userInfo:nil];
    }
    else if (price>1000){
        @throw [NSException exceptionWithName:@"价格异常" reason:@"价格偏高" userInfo:nil];
    }
    else{
        _price=price;
    }
}

-(void)setAge:(int)age{
    if (age<0) {
        @throw [YYAgeException ageExceptionWithReason:@"年龄小于0"];
    }
    else if (age>150){
       @throw [YYAgeException ageExceptionWithReason:@"年龄大于150"];
    }
    else{
        _age=age;
    }
}
@end
//  YYAgeException.h

#import <Foundation/Foundation.h>
/**
 *  描述年龄超出范围的情况
 */
@interface YYAgeException : NSException
-(instancetype)initWithReason:(NSString *)reason;
+(instancetype)ageExceptionWithReason:(NSString *)reason;
@end
//  YYAgeException.m

#import "YYAgeException.h"

@implementation YYAgeException
-(instancetype)initWithReason:(NSString *)reason{
    return self=[super initWithName:@"YYAgeException" reason:reason userInfo:nil];
}

+(instancetype)ageExceptionWithReason:(NSString *)reason{
    return [[self alloc]initWithReason:reason];
}
@end



//  异常执行顺序
//  test_exception1.m

#import "YYDemo.h"

int testReturn(){
    YYDemo* d1;
    @try {// 注意这里的try块不管是否有异常testReturn()都会返回3<打开此函数的注释验证>所已不应该在@finally
          // 中使用return语句(如果我想正常结束返回1不正常结束返回2,因为在finally中加了return就实现不了我的想法)
        d1=[YYDemo new];
        [d1 method1];//1.
//        [d1 method2];
        return 1;// return 1 之前会调用finally
    }
    @catch (NSException *ex) {
        NSLog(@"产生异常了");
        return 2;
    }
    @finally {
        NSLog(@"最终执行的代码");
//        return 3;
    }
    NSLog(@"testReturn结束");
    return 0;
}
int main_ex1(){
    int ret=testReturn();
    NSLog(@"ret=%d",ret);
    return 0;
}

// 几点注意
// 1>上面代码演示异常执行顺序
//try块中一旦有代码产生异常,则该行及其后的代码都不再执行,转到catch块中执行,执行完后进入finally块执行,执行完后如
//果还有代码则继续执行;try块中全部代码都没有产生异常,则跳过catch直接进入finally块执行,执行完后如果还有代码则继续
//执行;finally权限较高,即使在try或catch中有return,也必须等finally执行完才能返回,除非强制退出exit(0)函数;所以
//不建议在finally中有return语句

//2>注意事项
//a)@try是异常处理中必须出现的,@catch和@finally是可选的,但至少出现一个
//b)@finally是无论有没有产生异常、无论产生的异常是否捕捉到都要执行的,甚至return也不能影响其执行
//c)在@try块中定义的变量是无法在@catch和@finally中使用的
//d)不应该在@finally中使用return语句




// 抛出异常@throw的用法

//  test_ex2.m

#import "YYDemo.h"
int main_ex2(){
    YYDemo* d=[YYDemo new];
    @try{
        [d method2];
        d.price=-100;// 这里会抛出异常
    }
    @catch(NSException* ex){
        NSLog(@"ex.name:%@",ex.name);
        NSLog(@"ex.reason:%@",ex);
    }
    @finally{
        NSLog(@"最终处理");
    }
    return 0;
}




 // 自定义异常
//  test_ex3.m

#import "YYDemo.h"
int main_ex3(){
    YYDemo* d=[YYDemo new];

    @try {
        // 注意下面多处有异常但只有第一个发生异常的地方会被try到
        d.age=860;
        d.price=-20;
        [d method1];
        [d method2];
    }
    // 注意下面有两个catch,注意顺序(父子层次关系越低的越靠前,NSException肯定写在最后)
    @catch (YYAgeException* aex){// 小网捕捉放前面
        NSLog(@"年龄产生异常:%@",aex);
    }
    @catch (NSException *exception) {// 大网捕捉放后面
        NSLog(@"ex.name:%@",exception.name);
        NSLog(@"ex:%@",exception);
    }
    @finally {
        NSLog(@"finally");
    }
    return 0;
}


//自定义异常
//A.定义NSException的子类
//B.根据需要定义、重写相关方法
//C.抛出自定义异常和抛出NSException相同
//D.捕捉:注意顺序(父子层次关系越低的越靠前,NSException肯定写在最后)






// OC的异常处理机制不适用于C的函数,但可以通过其他方式来辅助判断是否出现异常
//  test_ex4.m

#import <Foundation/Foundation.h>
int main_ex4(){
    char chs[1000]={0};
    int a;
    scanf("%s",chs);
    a=atoi(chs);//ASCII to Int

    NSLog(@"a=%d",a);

    NSString* s1=[NSString stringWithUTF8String:chs];
    NSString* s2=[NSString stringWithFormat:@"%d",a];
    if ([s1 isEqualToString:s2]) {
        NSLog(@"ok");
    }
    else{
        NSLog(@"input error");
    }
    return 0;
}


三、包装类
1.作用:将C语言的基本类型封装成OC对象,以供Foundation框架库使用
2.不同数据类型封装方法不同,每个封装方法都有对应的拆包方法
3.NSNumber主要用于包装数值类型,如:int、float、char等
4.NSValue主要用于包装指针、特定结构体类型,如:Size、Point

// 演示包装类
//  test_number.m

#import <Foundation/Foundation.h>
int main(){
    int a=10;
    NSNumber* n1=[NSNumber numberWithInt:a];
    NSLog(@"n1=%@,n1=%d",n1,[n1 intValue]);
    NSPoint pt={10,20};
    NSRect rt={pt,{100,80}};
    NSValue* v1=[NSValue valueWithRect:rt];
    NSLog(@"v1:%@",v1);
    NSNumber* n2=@(100);
    NSNumber* n3=@(a);//@a是错的(@后直接加英文编译系统认为它可能是摸个类似与@interface的指令)
    NSLog(@"n2:%@,n3:%@",n2,n3);
    return 0;
}

// 运行结果
//2015-12-24 01:20:24.591 1223[2497:120787] n1=10,n1=10
//2015-12-24 01:20:24.592 1223[2497:120787] v1:NSRect: {{10, 20}, {100, 80}}
//2015-12-24 01:20:24.592 1223[2497:120787] n2:100,n3:10
//Program ended with exit code: 0

===============EOF=====================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值