博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Objective-C 基础入门(一)
阅读量:4079 次
发布时间:2019-05-25

本文共 7438 字,大约阅读时间需要 24 分钟。

目录

 


一、什么是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;@endBNRStockHolding.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<Foundation/Foundation.h>

@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.继承

标题

创建 

#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。

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

给对象发送消息的时候,对象就会通过 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 指针标识所属关系。

  • 当使用 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。

 

 

 

 

转载地址:http://gmxni.baihongyu.com/

你可能感兴趣的文章
斯坦福大学机器学习——因子分析(Factor analysis)
查看>>
ssh 如何方便的切换到其他节点??
查看>>
Java实现DES加密解密
查看>>
HTML基础
查看>>
Java NIO
查看>>
Java大数据:Hbase分布式存储入门
查看>>
大数据学习:Spark RDD操作入门
查看>>
大数据框架:Spark 生态实时流计算
查看>>
大数据入门:Hive和Hbase区别对比
查看>>
大数据入门:ZooKeeper工作原理
查看>>
大数据入门:Zookeeper结构体系
查看>>
大数据入门:Spark RDD基础概念
查看>>
大数据入门:SparkCore开发调优原则
查看>>
大数据入门:Java和Scala编程对比
查看>>
大数据入门:Scala函数式编程
查看>>
【数据结构周周练】002顺序表与链表
查看>>
C++报错:C4700:使用了非初始化的局部变量
查看>>
C++类、结构体、函数、变量等命名规则详解
查看>>
C++ goto语句详解
查看>>
【数据结构周周练】008 二叉树的链式创建及测试
查看>>