Objective-C 基础入门(一)

目录

 

一、什么是Objective-C?

Hello world

Tips:

二、Objective-C的类

1.新建一个OC类

self 指针

Tips:

2.NSString

创建实例

NSString方法

3.NSArray

创建数组

遍历数组

NSMutableArray

4.属性

声明属性

属性的特性

5.继承

创建 

覆盖方法

super

继承层次

6.类扩展

7.循环引用与内存泄露

弱引用


一、什么是Objective-C?

  1. 是扩充C的面向对象的编程语言;OC可以完全兼容C语言,在OC中可以随便写C代码,甚至部分的C++代码。(其他类似的面向对象编程语言:C ——> C++;Objective-C;C #)
  2. Objective-C用来可发 Mac OS X 平台与 iOS 平台的应用程序

Hello world

#import 
//类比#include<>  <>引用的是系统库;""引用自己定义的类

int main(int argc,const char * argv[])
{
    @autoreleasepool{
    //自动释放池
    
    NSLog(@"Hello World!");

    }
    return 0;
}

Tips:

  1. 输出语句 NSLog ( @"Hello World!" );  NSLog 是自动换行的,即无需 ‘ \n ’!
  2. command + R 运行;command + B 编译

二、Objective-C的类

1.新建一个OC类

  • 新建一个类时会自动创建.h 与.m 两个文件,其中.h文件只包含声明不实现;.m文件实现声明的方法。
  • 创建语句:

Person *per = [[Person alloc]init];

Person *per = [Person new];

BNRStockHolding.h
#import

@interface BNRStockHolding:NSObject
{
    float _purchaseSharePrice;
    float _currentSharePrice;
    int _numberOfShares;
}

-(void)setPurchaseSharePrice:(float)p setCurrentSharePrice:(float)c... 
       setNumberOfShares:(int)n;

-(float)costInDollars;
-(float)valueInDollars;

@end


BNRStockHolding.m:
#import"BNRStockHolding.h"

@implementation BNRStockHolding

-(void)setPurchaseSharePrice:(float)p setCurrentSharePrice:(float)c...
       setNumberOfShares:(int)n
{
    _purchaseSharePrice=p;
    _currentSharePrice=c;
    _numberOfShares=n;
}

-(float)costInDollars
{
    return _purchaseSharePrice*_numberOfShares;
}
-(float)valueInDollars
{
    return _currentSharePrice*_numberOfShares;
}

@end


​main函数:
#import 
#import "BNRStockHolding.h"

int main ()
{
@autoreleasepool{
    printf("My StockHolding:\n");
    NSMutableArray *list=[[NSMutableArray alloc] init];

    BNRStockHolding *A=[[BNRStockHolding alloc] init];
    BNRStockHolding *B=[[BNRStockHolding alloc] init];
    BNRStockHolding *C=[[BNRStockHolding alloc] init];
    
    [A setPurchaseSharePrice:12 setCurrentSharePrice:14.5 setNumberOfShares:32];
    [B setPurchaseSharePrice:17 setCurrentSharePrice:12.3 setNumberOfShares:25];
    [C setPurchaseSharePrice:32 setCurrentSharePrice:27.5 setNumberOfShares:43];
    
    [list addObject:A];
    [list addObject:B];
    [list addObject:C];
    int i=1;
    for(BNRStockHolding *t in list)
        NSLog(@"第 %d 支股票的购入价为 %.2f,市值为 %.2f。",i++,[t costInDollars],
                                                             [t valueInDollars]);
    }
    return 0;
}

头文件以 @interface 开始,以 @end 结束。注意要在花括号中声明成员变量。 

  • 实例变量
  1. 变量属性默认相当于 C++ 中的 private,只能通过实例方法进行存取
  2. 变量命名以 _ 开头(后续会提到带 _ 的为实参,不带 _ 的为形参)。
  • 实例(对象)方法(区别于类方法)命名规则:
  1. 以 - 号开头,所有数据类型写在()
  2. 函数名与参数列表之间用连接
  3. - ( 返回值类型 ) 函数名 : 参数类型 参数名
  4. 调用格式 [ 对象指针 函数名 : 参数 ]

self 指针

相当于 C++ 中的 this 指针,可以在类的方法中调用对象自身的方法;还可以将 self 做为实参传递给其他方法,以便其访问“当前的”对象。例如:

-(void)addYourselfToArray:(NSMutableArray*)theArray
{
    [theArray addObject:self];
}

Tips:

  1. 不能丢掉:NSObject ,绝大部分类的基类都是 NSObject,它实现了引用计数的内存管理模型。
  2. 只有函数实现没有函数声明可以运行,但这是Objective-C的弱语法,不推荐使用。
  3. @autoreleasepool 自动释放池:作用是在运行时延迟释放,系统自动跟踪每个对象的使用情况,并在释放AutoreleasePool时,释放池中的全部对象。在正常情况下,创建的变量会在超出其作用域的时候release,但是如果将变量加入AutoreleasePool,那么release将延迟执行。
  4. Objective-C 没有命名空间,所以最好为类名加上特殊前缀,避免命名冲突。

2.NSString

创建实例

创建一个 NSString 字符串常量实例:

NSString *lament = @"Why me!";

用变量创建一个字符串实例:

NSString *dateString  = [NSString stringWithFormat:@"The date is %@",now];

stringWithFormat:方法后面跟着一个格式字符串作为参数,这个格式字符串带有一个变量,变量的值类似与NSLog一样替换格式说明符。

NSString方法

  • -(NSUInteger)length 返回字符串的长度,包括空格
NSUInterger charCount = [dateString length];
  • -(BOOL)isEqualToString:(NSString *)other 查看一个字符串是否和另一个字符串相等
if([A isEqualToString:B])
    NSLog(@"%@ and %@ are equal.",A,B);
  • -(NSString *)uppercaseString 将字符串变成大写形式
NSString *A = @"That makes me so happy!";
NSString *B =[A uppercaseString];
  • -(NSRange)rangeOfString:(NSString*)s 查找字符及子字符串
NSString listOfNames = @"..." //名单
NSString name = @"Ward";
NSRange match = [listOfNames rangeOfString:name];
if(match.location == NSNotFound)
    NSLog(@"No match found!");
else
    NSLog(@"Match!");

返回值 NSRange 是一个结构,包含 location 和 length 两个值。如果找不到目标子字符串则返回 NSNotFound

3.NSArray

创建数组

与 NSString 相似,NSArray 也可以用字面常量语法创建实例。数组的内容写在方括号里,使用逗号分隔,前方带有@符号

NSArray *dateList = @[now,tomorrow,yesterday];

NSArray 的实例是无法改变的,一旦 NSArray 实例被创建后,就无法添加或删除数组里的元素也无法改变数组元素的顺序

遍历数组

for(int i=0;i<[dateList count];i++)
{
    NSLog(@" %@",dateList[i]);
}

Objective-C 提供一种简化的 for 循环语法,称为快速枚举。省去了对数组计数的同时,高效地遍历数组的所有元素。

for(NSDate *d in dateList)
{
    NSLog(@"Here is a date: %@.",d);
}

类似于 C++ 中的 auto 遍历语法。

NSMutableArray

可以添加、删除或对元素重新进行排序。(NSMutableArray 是 NSArray 的子类)

NSMutableArray *dateList =[NSMutableArray array];    //创建空数组

//将两个 NSDate 对象加入新创建的数组
[dateList addObject:now];
[dateList addObject:tomorrow];

//将 yesterday 指针插入数组的起始位置
[dateList addObject:yesterday atIndex:0];

//删除 yesterday 指针
[dateList removeObjectAtIndex:0];

//快速遍历
for(NSDate *d in dateList)
{
    NSLog(@"Here is a date: %@.",d);
}
//在数组中查询是否有和 anObject 相等、相同的元素
-(NSUInteger) indexOfObject:(id) anObject;
-(NSUInteger) indexOfObjectIdenticalTo:(id) anObject;

创建:上述程序使用了 array 类方法来创建 NSMutableArray,等同于 [[NSMutableArray alloc] init];

添加:addObject :元素 方法自动在尾部添加元素,如果要将对象添加到一个特定的索引上,则可以使用 insertObject:atIndex:下标。

删除:removeObject:atIndex:下标 数组对象的计数也随之会减小。

遍历:不可在快速枚举过程中添加或者删除对象

4.属性

声明属性

在自定义的类中删除实例变量,然后用两个属性重写存取方法的声明:

  1. 属性的声明以 @property 开始,然后是属性的类型和名称
  2. 编译器会自动根据声明的属性声明与实现存取方法

BNRStockHolding.h
#import

@interface BNRStockHolding:NSObject
@property (nonatomic) float purchaseSharePrice;
@property (nonatomic) float currentSharePrice;
@property (nonatomic) int numberOfShares;

{
    float _purchaseSharePrice;
    float _currentSharePrice;
    int _numberOfShares;

}

-(void)setPurchaseSharePrice:(float)p setCurrentSharePrice:(float)c... 
       setNumberOfShares:(int)n;

-(float)costInDollars;
-(float)valueInDollars;

@end

.m文件中只需实现 costInDollars 与 valueInDollars 方法。

属性的特性

属性的特性会显示在 @property 后的括号中,属性第一可选项为

  • 非原子性 nonatomic
  • 原子性 atomic

与多线程有关,原子性保证多线程的安全;省略此选项时默认为原子属性

属性的第二可选项为

  • 只读 readonly
  • 读写 readwrite

只读特性的值只能读取不能改写,编译器为其只生成取方法,不生成存方法;省略此选项时默认为读写属性

使用属性标识的变量,在方法中使用到时,必须用 self.变量名

  • 属性可以用点号调用存取方法

[mikey setWeightInKilos:96];
[mikey setHeightInMeters:1.8];

mikey.WeightInKilos = 96;
mikey.HerghtMeters = 1.8;

使用点调用的时候是在发送消息。

public 成员只能用 ->

5.继承

Objective-C 基础入门(一)_第1张图片 标题

创建 

#import "BNRPerson.h"
@interface BNREmployee:BNRPerson

@property (nonatomic) unsigned int employeeID;
@property (nonatomic) unsigned int officeAlarmCode;
@property (nonatomic) NSDate *hireDate;
-(double)yearsOfEmployment;

@end

其中 hireDate 属性是指向另一个对象的属性,属性值想对象的时候,需要对内存进行管理。

覆盖方法

覆盖方法的时候只能改变方法的实现,没有必要在.h文件中声明,相应的声明在继承的父类中已经写出。方法的名称、返回类型及实参类型等都必须保持相同。

super

覆盖一个方法的时候。子类可以利用父类方法的结果,而不是整个替换。调用格式为:

[super 实例方法名]

-(float)bodyMassIndex
{
    float normalBMI = [super bodyMassIndex];
    return normalBMI * 0.9;
}

继承层次

基本所有的类都继承自 NSObject。

Objective-C 基础入门(一)_第2张图片

NSObject 拥有很多方法,但是只有一个实例变量:isa 指针。指针类型为创建该对象的类。

Objective-C 基础入门(一)_第3张图片

给对象发送消息的时候,对象就会通过 isa 指针找到该对象的类查询是否有该消息名的方法,如果没有则查询它的父类。但是如果使用 super 指令,就等于告诉对象,从对象的父类开始查找与之匹配的指定的方法。

由于继承中子类只 import 了父类的头文件,所以看不到父类之中的变量与函数,所以变量通过 self.变量名 操作。

6.类扩展

不是所有的属性或方法都需要在类的头文件中声明,有的属性或方法是类的内部或者类的实例才需要使用的,设计实现细节的属性或方法最好在类扩展中声明。类似于私有成员与函数

#import "Employee.h"
@interface Employee()
@property (nonatomic) unsigned int officeAlarmCode;
@end

@implementation Employee
...

类扩展以 @interface 开始,@end 结束。类名后面加 ()。这样的改动会让变量成为私有成员。

  • 在类外不能通过 对象名 . officeAlarmCode 访问这个变量

7.循环引用与内存泄露

Employee 持有一个 Asset* 类型的 holder 指针标识持有关系,每一个 Asset 中也存在一个 Employee* 类型的 holder 指针标识所属关系。

Objective-C 基础入门(一)_第4张图片

  • 当使用 Asset 类和 Employee 类时,为了保持两者间的关系一致,可以在将 所属对象加入主对象的 collection 对象的同时,设置指向主对象的指针
-(void)addAsset:(Asset*)a
{
    if(!assets)
    {
        assets = [NSMutableArray new];
    }
    [assets addObject:a];
    a.holder = self;
}

以上简单处理的“相互拥有”的所属关系导致的相关对象都无法被释放,这种情况就是 强循环引用 导致的内存泄露。

  • 类似与 C++ 中的 weakptr,此处需要引入弱引用的思想解决泄露问题。

弱引用

弱引用是不说明所有权的指针,不增加引用计数

@property (nonatomic, weak) Employee *holder;
    或
_weak Employee *holder;

当弱引用指向的对象被释放时,相应的指针变量会被复位 nil。

 

 

 

 

你可能感兴趣的:(Objective-C)