目录
一、什么是Objective-C?
Hello world
Tips:
二、Objective-C的类
1.新建一个OC类
self 指针
Tips:
2.NSString
创建实例
NSString方法
3.NSArray
创建数组
遍历数组
NSMutableArray
4.属性
声明属性
属性的特性
5.继承
创建
覆盖方法
super
继承层次
6.类扩展
7.循环引用与内存泄露
弱引用
#import
//类比#include<> <>引用的是系统库;""引用自己定义的类
int main(int argc,const char * argv[])
{
@autoreleasepool{
//自动释放池
NSLog(@"Hello World!");
}
return 0;
}
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 结束。注意要在花括号中声明成员变量。
相当于 C++ 中的 this 指针,可以在类的方法中调用对象自身的方法;还可以将 self 做为实参传递给其他方法,以便其访问“当前的”对象。例如:
-(void)addYourselfToArray:(NSMutableArray*)theArray
{
[theArray addObject:self];
}
创建一个 NSString 字符串常量实例:
NSString *lament = @"Why me!";
用变量创建一个字符串实例:
NSString *dateString = [NSString stringWithFormat:@"The date is %@",now];
stringWithFormat:方法后面跟着一个格式字符串作为参数,这个格式字符串带有一个变量,变量的值类似与NSLog一样替换格式说明符。
NSUInterger charCount = [dateString length];
if([A isEqualToString:B])
NSLog(@"%@ and %@ are equal.",A,B);
NSString *A = @"That makes me so happy!";
NSString *B =[A uppercaseString];
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。
与 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 是 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:下标 数组对象的计数也随之会减小。
遍历:不可在快速枚举过程中添加或者删除对象。
在自定义的类中删除实例变量,然后用两个属性重写存取方法的声明:
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 后的括号中,属性第一可选项为
与多线程有关,原子性保证多线程的安全;省略此选项时默认为原子属性。
属性的第二可选项为
只读特性的值只能读取不能改写,编译器为其只生成取方法,不生成存方法;省略此选项时默认为读写属性。
使用属性标识的变量,在方法中使用到时,必须用 self.变量名
[mikey setWeightInKilos:96];
[mikey setHeightInMeters:1.8];
mikey.WeightInKilos = 96;
mikey.HerghtMeters = 1.8;
使用点调用的时候是在发送消息。
public 成员只能用 ->
#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 实例方法名]
-(float)bodyMassIndex
{
float normalBMI = [super bodyMassIndex];
return normalBMI * 0.9;
}
基本所有的类都继承自 NSObject。
NSObject 拥有很多方法,但是只有一个实例变量:isa 指针。指针类型为创建该对象的类。
给对象发送消息的时候,对象就会通过 isa 指针找到该对象的类查询是否有该消息名的方法,如果没有则查询它的父类。但是如果使用 super 指令,就等于告诉对象,从对象的父类开始查找与之匹配的指定的方法。
由于继承中子类只 import 了父类的头文件,所以看不到父类之中的变量与函数,所以变量通过 self.变量名 操作。
不是所有的属性或方法都需要在类的头文件中声明,有的属性或方法是类的内部或者类的实例才需要使用的,设计实现细节的属性或方法最好在类扩展中声明。类似于私有成员与函数。
#import "Employee.h"
@interface Employee()
@property (nonatomic) unsigned int officeAlarmCode;
@end
@implementation Employee
...
类扩展以 @interface 开始,@end 结束。类名后面加 ()。这样的改动会让变量成为私有成员。
Employee 持有一个 Asset* 类型的 holder 指针标识持有关系,每一个 Asset 中也存在一个 Employee* 类型的 holder 指针标识所属关系。
-(void)addAsset:(Asset*)a
{
if(!assets)
{
assets = [NSMutableArray new];
}
[assets addObject:a];
a.holder = self;
}
以上简单处理的“相互拥有”的所属关系导致的相关对象都无法被释放,这种情况就是 强循环引用 导致的内存泄露。
弱引用是不说明所有权的指针,不增加引用计数。
@property (nonatomic, weak) Employee *holder;
或
_weak Employee *holder;
当弱引用指向的对象被释放时,相应的指针变量会被复位 nil。