[程序员日记]Objective-C基本语法总结

一 类

1.类和对象的定义

成员变量的声明

NSString *  _变量名

成员变量的Setter和Getter方法

一个类可以有多个构造方法
构造方法(作用是初始化一个类)

无参构造方法
- (id/类名 */) init {};

有参构造方法
- (id/类名 */) initWith…. {};

类方法

类方法不可访问成员变量
不可以调用对象方法
作用
创建对象
+ (id)defualtClass{
Dog *dog =[ [Dog alloc] init];
….
[dog release];
}
通过类方法可以对外暴露一个功能模块的接口

[Dog start];
+ (id) start{
Dog *dog =[ [Dog alloc] init];
….
[dog release];
}

创建单例对象
+ (Dog *) defaultDog{
static Dog * dog = nil;
if (dog ==nil){
dog = [[Dog alloc] init] ;
}
return dog;
}

+ (Dog *)defaltDog {
    //声明一个Dog类的静态指针,存储在数据段,默认为空
    static Dog * dog;
    if (!dog) {
        //如果dog为空时,才创建dog对象
        dog = [[Dog alloc] init];
    }
    //这个方法只有在第一次调用时,才开辟空间,创建对象
    //以后调用,得到的都是第一次调用时创建的对象,是同一个对象,所有指针指向同一个地址
    //这个方法会创建出单例对象
    return dog;
}

类别

1.类别可以添加对象方法和类方法
2.类别不可以添加成员变量
3.用类别添加到某个类方法,就如同添加到原类中一样
4.类别添加的方法可以访问成员变量
5.父类中用类别添加的方法,子类也可以用

二 字符串操作

不可变字符串

字符串创建

NSString * str = @"ada";
NSString * str1 = [[NSString alloc] initWithString:@"fsf"];

Format可以实现字符串拼接

NSString * str2 = [[NSString alloc] initWithFormat:@"dfsf,%f",3.0];

将C字符串转化为OC字符串

NSString * str3 = [[NSString alloc] initWithUTF8String:"vsfsg"];

每个alloc+init方法,否有对应的方法

NSString * str1 = [[NSString StringWithString:@"fsf"];
NSString * str2 = [[NSString StringWithFormat:@"dfsf,%f",3.0];
NSString * str3 = [[NSString  StringWithUTF8String:"vsfsg"];

OC字符串与基础数据类型的转换

 floatValue 
 intValue 
 integerValue 
 boolValue

获取字符串长度

[str length]

获取字符串制定位置的字符

[str characterAtIndex:i]

字符串常用操作

比是否相等

 [a isEqualToString:b]  (返回值是Bool)

比大小

  [a compare:b] (0,相等;1,a>b;-1,a<b)

提取子串

[father subStringFromIndex:5] from 闭区间
[father subStringToIndex:3] to 开区间
[father subStringWithRange:NSMakeRange(4,5)]  第一个数定位,第二个数表示取得长度

改变大小写

uppercaseString 
lowercaseString

判断某个字符串是否是以另一个字符串开头或者是结尾

  hasPrefix 开头    
  hasSuffix  结尾

可变字符串

重置字符串

[str setString:] 

追加

[str appendString:]

插入

[str insertString:]

删除

[str deleteCharacterInRange:NSMakeRange(location.length)]

修改

  [str replaceCharacterInRange:NSMakeRange(location,length) withString:]

字符串分割

[str componentsSeparatedByString:](以单个字符分割)

[str componentsSparatedByCharactersInSet:[NSCharacterSet characterSetWithCharatersInString:]](以多个字符分割)

数组元素拼接

 [arr componentsJoinedByString:]

三 数组

数组的常用方法

获取数组下标

 [arr objectAtIndex:]  

取数组尾元素

[arr lastObject]  

获取数组元素个数

[arr count]  

获得某个下标的元素

[arr objectAtIndex:] 

重置数组

 [arr setArray:] 

追加

[arr addObject:] 

插入

[arr insertObject:  atIndex:] 

按照下标删除

[arr removeObjectAtIndex:]
[arr removeObject:] 

删除所有元素

[arr removeAllObjects]

删除最后一个

[removeLastObjct]

替换

[arr replacrObjectAtIndex:  withObject:]  

交换位置

[arr exchangeObjectAtInde:   withObjectAtIndex:]

增加元素

[arr addObject:]
[arr addObjectsFromArray:]

四 字典

传入键,取值

 [dic objectForKey:]  

获取键值对数

[dic count]  

得到所有的键

[dic allKeys]  

得到所有的值

[dic allValues]  

重置字典

[dic setDictionary]   

增加

[dic setObject: forKkey:]  

删除

[dic removeObjectForKeys:]  

删除所有键值对

[dic removeAllObjects] 

比较字符串大小

[str compare:str2]
[str isEqualToString:str1]

五 选择器

SEL sel = @selector(run);

这个方法用于编译时就能确定调用的方法

SEL sel = NSSelectorFromString(@"run");

这个方法用于运行时确定调用的方法

选择器定义

@selector把参数中的消息(crash),转化为选择器常量,存储到了SEL变量

    SEL sel = @selector(crash);

选择器实现

[对象 performSelector: ]
[对象 performSelector: withObject:]

performSelector方法最多只支持2个参数
如果有两个以上的参数,可以自己封装一个数据存储类,信息存储类里面有多个成员变量,传参的时候穿一个对象就可以了
可以传一个数组或者字典,如果传的是个字典的话,字典的键就得事先约定好

SEL sel2 = @selector(invesAPerson:);
NSDictionary * dic = @{@"name":@"博雅·汉库克", @"sex":@"女", @"motto":@"我要嫁给路飞"};

消息实现:
– (void)invesAPerson:(NSDictionary *)infoDic {

    NSString * name = infoDic[@"name"];
    NSString * sex = infoDic[@"sex"];
    NSString * motto = infoDic[@"motto"];

    NSLog(@"姓名: %@, 性别: %@, 座右铭: %@", name, sex, motto);
}

选择器用法

实现比较
– (BOOL)isLongerThanAnotherLavra:(Lavra *)newLavra {
return [self length] > [newLavra length];
}
SEL sel = @selector(isLongerThanAnotherLavra:);
[array sortArrayWithSelector:sel];//自己定义方法
[array sortUsingSelector : sel] //NSMutableArray自带的一个排序方法

- (void)sortArrayWithSelector:(SEL)selector {
    //冒泡排序
    for (int i = 0; i < [self count] - 1; i++) {
        for (int j = 0; j < [self count] - i - 1; j++) {
            //这个if是想判断 self[j] 和 self[j + 1]
            //判断结果,是由参数selector决定的
            //[虫子的对象   发一个消息(selector里面装的消息)(传了参数是另一个虫子)]
            if ([self[j] performSelector:selector withObject:self[j + 1]]) {
                [self exchangeObjectAtIndex:j withObjectAtIndex:j + 1];
            }
        }
    }
}

选择器常用的方法
判断对象能否响应某个消息
respondsToSelector: 是OC常用的方法

作用

可以使用一个方法实现不同的功能,提高代码复用度
选择器支持iOS开打中的控件的响应机制
可以用于方法的回调

Class class是一种变量类型,装类的类型(相当于int)

六 点语法

setter方法用于给成员变量赋值
getter方法用于返回成员变量的值
OC里面点语法,不是直接访问成员变量,而是调用setter和getter方法

七 继承

(oc的继承是动态继承,编译的时候不能确定父类是谁,在运行的时候才可以确定)
子类没有声明的成员变量,属性,方法,但可以直接用父类的,这就是继承
子类可以继承父类的成员变量,属性,方法
但是父类没有声明在头文件里的成员变量,属性,方法,子类是继承不到的

重写:1.完全重写 2,在父类的基础上重写
重写也是多态的体现,再重写的方法中可以用super可以直接调用父类的方法

派生:子类可以派生出父类没有的方法属性,父类不能访问

重载:一簇方法功能是一样的,区别在于参数的个数,这就叫重载

八 多态

有,重写,重载,虚函数,其实就是同一个接口的不同实现

【虚函数】父类的指针可以指向子类对象
不看指针看对象的方法,称为虚函数

- (void)beatWorm:(Worm *)worm;

形参是父类的对象,地址可以传子类的地址

九 工厂模式

工厂模式,其实是多个类共同组成的,对外他们使用同一个类名

@implementation LNBString

+ (LNBString *)string1 {
    TaggedString * str = [[TaggedString alloc] init];
    return str;
}
+ (LNBString *)string2 {
    CFString * str = [[CFString alloc] init];
    return str;
}
   -(void)print;
    @end

@implementation TaggedString

-(void)print {
    NSLog(@"CFString");
}
@end

@implementation CFString

- (void)print {
    NSLog(@"CFString");
}

@end

    LNBString * str1 = [LNBString string1];
    LNBString * str2 = [LNBString string2];
    
    [str1 print];
    [str2 print];

    NSLog(@"%@, %@", [str1 class], [str2 class]);

十 内存管理

1.内存管理常见的问题

只申请不释放【内存泄露】
释放内存后,依旧访问这段内存【内存提前释放】
多次释放同一段内存【内存重复释放】
【内存管理的方法】引用计数内存管理

2,setter和getter方法分析

setter方法
    NSArray * arr = [[NSArray alloc] init];  //a = 1
    Dog * dog3 = [[Dog alloc] init];  //d = 1
    [dog3 setArray:arr];  //a = 2
    
    [arr release];  //数组被释放   a = 1
    arr = nil;
    
    NSArray * newArr = [[NSArray alloc] init];  //new == 1
    [dog3 setArray:newArr];   //new == 2
    [newArr release];   //new == 1
    
    [dog3 setArray:newArr];

   - (void)setArray:(NSArray *)array {
       if(_array != array) {
           [_array release];
           _array = [array retain];
       }
   }
getter方法
    Dog * dog4 = [[Dog alloc] init];
    NSArray * arr4 = [[NSArray alloc] init];  //arr4 == 1
    [dog4 setArray:arr4];   //arr4 == 2
    [arr4 release];  //arr4 == 1
    
    NSArray * arr5 = [dog4 array];   //arr4  == 1
    
    [dog4 release];  //arr4被释放

   - (NSArray *)array {
       return [[_array retain] autorelease];
   }
拷贝消息

字符串本身已经实现了拷贝协议,所以一般来讲,拷贝操作只用于字符串
【归档】方法实现自己封装类的对象拷贝
retain并不产生新的对象,两个指针指向同一个对象。
copy会复制源对象,产生新的对象,产生的新对象,不可修改。
mutableCopy也复制对象,复制产生的新对象可以修改。
实际工作中,只有字符串,使用copy或mutableCopy,其他都用retain

【单例不需要内存管理】

内存管理法则

a.凡是用alloc, retain, new(或使用new开头的方法), copy(或使用copy开头的方法), mutableCopy(或使用mutableCopy开头的方法)操作的对象,都必须使用release或autorelease方法进行释放。
b.谁创建,谁释放。(谁+1,谁-1)

十一 协议与代理

【数据下下载,怎么把字符串转化成统一资源定位符】

NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
NSString * str = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL * newURL = [NSURL URLWithString:str];
NSData * data = [[NSData alloc] initWithContentsOfURL:newURL];

协议

协议里面规定的方法缺省属性是必须实现的
协议里面可以声明可选实现方法
@protocol HttpRequestDelegate <NSObject>

//@required标识符下面的方法为必须实现的协议方法

@required 
- (void)downloadFinished:(NSData *)data;

//@optional标识符下面的方法为可选实现的协议方法

 @optional 
- (void)sleep;

@end

@interface HttpRequest : NSObject

代理指针

@property (assign) id<HttpRequestDelegate> delegate;

下载数据

- (void)downloadDataWithURL:(NSString *)url;

@end

委托方

@implementation HttpRequest

下载数据
– (void)downloadDataWithURL:(NSString *)url {
//同步下载
//NSData就是一堆二进制数据,纯粹为了存储数据
//字符串转化为统一资源定位符,不支持中文汉字

    //用UTF8编码格式将字符串重新编码
    NSString * urlStr = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

代理方

@interface DataManager : NSObject <HttpRequestDelegate>

通过一个统一资源定位符获取数据
– (void)loadDataWithURL:(NSString *)url;

@end

@implementation DataManager {
    //把数据下载类生命成自己的成员变量,以便调用下载方法
    HttpRequest * _request;
}

- (instancetype)init {
    if (self = [super init]) {
        _request = [[HttpRequest alloc] init];
        //设置代理指向,代理就是当前对象
        //把自己成员变量的代理设为自己
        _request.delegate = self;
    }
    return self;
}

- (void)dealloc {
    [_request release];
    _request = nil;
    [super dealloc];
}

- (void)loadDataWithURL:(NSString *)url {
    //希望开始加载数据,但是下载数据的任务不属于数据管理类
    //在这里调用数据下载类的方法,进行数据下载
    [_request downloadDataWithURL:url];
}

#pragma mark - 实现协议里面的方法
- (void)downloadFinished:(NSData *)data {
    //把data转化为字符串,打印
    NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@", str);

    [str release];
}

@end

十二 Block

【委托方】

对外暴露下载方法

@interface HttpRequest : NSObject

@property (copy) void (^finished)(NSData *);

- (void)downloadWithURL:(NSString *)url;

@end

对外暴露下载方法

@implementation HttpRequest


- (void)downloadWithURL:(NSString *)url {
//开辟子线程的方式下载
//Target:表示这个消息的接受者,第二个参数为消息,第三个参数为传的参
    NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadFunc:) object:url];
    //子线程开始运行
    [thread start];
    //子线程的release会在执行完任务之后生效
    [thread release];  
}

- (void)threadFunc:(NSString *)url {
    //模拟一下下载耗时
   sleep(5);

   //下载数据
    NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
    //把下载好的数据回传给调用者
    _finished(data);

    [data release];
}

- (void)dealloc {
    self.finished = nil;
    [super dealloc];
}
@end

【代理方】

数据管理类开始加载数据

@interface DataManager : NSObject

- (void)loadData:(NSString *)url;

@end

@implementation DataManager {
    //把数据下载类,声明成数据管理类的成员变量
    HttpRequest * _request;
    int _a;
}

- (instancetype)init {
    if (self = [super init]) {
        //创建成员变量对象
        _request = [[HttpRequest alloc] init];
    }
    return self;
}

- (void)dealloc {
    [_request release];
    _request = nil;
    [super dealloc];
}

- (void)bark {

}

数据管理类开始加载数据

- (void)loadData:(NSString *)url {
    //调用数据下载类的方法,开始下载数据

    _request.finished = ^(NSData * data) {
        //Block真正实现的地方
        NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@", str);
        [str release];
    };

    [_request downloadWithURL:url];
}

@end

另一种实现

【委托方】

@interface Worker : NSObject
@property (copy) void (^finished)(NSUInteger);
//买电脑的方法
//添加一个Block回调的参数
- (void)buyMacWithNumber:(NSUInteger)num withFinished:(void (^)(NSUInteger))finished;
void (^)(NSUInteger)
@end


@implementation Worker
- (void)dealloc {
    self.finished = nil;
    [super dealloc];
}

- (void)buyMacWithNumber:(NSUInteger)num withFinished:(void (^)(NSUInteger))finished {
    NSLog(@"工人买回了电脑.");
    //信息通过Block回传
    finished(num);
}

【代理方】

@interface Boss : NSObject

//发起买电脑的方法
- (void)wantToBuyMacWithNum:(NSUInteger)num;

@end

@implementation Boss {
    Worker * _worker;
}
- (void)dealloc {
    [_worker release];
    _worker = nil;
    [super dealloc];
}

//发起买电脑的方法
- (void)wantToBuyMacWithNum:(NSUInteger)num {
    //自己不会买电脑,需要调用Worker的买电脑方法
    if (_worker == nil) {
        //创建成员变量对象
        _worker = [[Worker alloc] init];
    }
    [_worker buyMacWithNumber:num withFinished:^(NSUInteger num) {
        //买回来电脑之后执行的代码
        NSLog(@"老板收到了%lu台MAC.", num);
    }];
}
@end

十三 文件操作

1.获取NSFileManager对象

NSFileManager * manager = [NSFileManager defaultManager];

2.文件浅遍历

NSError * error = nil;
NSArray * arr = [manager contentsOfDirectoryAtPath:PATH error:&error];
if (error != nil) {
   NSLog(@"%@", error);
}
NSLog(@"%@", arr);

3.文件路径的深遍历

NSArray * arr1 = [manager subpathsOfDirectoryAtPath:PATH error:nil];
NSLog(@"%@", arr1);

4.判断文件/路径是否存在

BOOL result = [manager fileExistsAtPath:PATH];
NSLog(@"%d", result);

BOOL isDir;
BOOL result1 = [manager fileExistsAtPath:PATH isDirectory:&isDir];
if (isDir == YES) {
    NSLog(@"是路径");
}else {
    NSLog(@"不是路径");
}

5.创建一个文件路径

NSError * error1 = nil;

创建文件路径的时候,一定要把路径名写全

path1 = @"/Users/naibin/Desktop/FileManager/MIDDLE/ACE"
NSString * path1 = [PATH stringByAppendingPathComponent:@"MIDDLE/ACE"];
NSString * path2 = [PATH stringByAppendingFormat:@"/ACE%d", 9];

NSDictionary * dic = [manager attributesOfItemAtPath:PATH error:nil];

[manager createDirectoryAtPath:path1 withIntermediateDirectories:YES attributes:nil error:&error1];
if (error1 != nil) {
   NSLog(@"%@", error1);
}

创建一个文件,文件里有内容

NSString * str = @"我是一个字符串";
NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding];
[manager createFileAtPath:[PATH stringByAppendingPathComponent:@"abc.txt"] contents:data attributes:nil];

6.拷贝一个文件/路径

通过FileManager创建、拷贝、移动一个文件或者路径,如果存在同名文件或者路径的话,就返回操作失败

[manager copyItemAtPath:[PATH stringByAppendingPathComponent:@"c"] toPath:[PATH stringByAppendingPathComponent:@"OTHERS/c"] error:nil];

7.删除文件或者路径

[manager removeItemAtPath:[PATH stringByAppendingPathComponent:@"OTHERS/c"] error:nil];

8.移动某个文件或者路径
【注】拷贝、移动操作,拷贝、移动的结果目录一定要写全

[manager moveItemAtPath:[PATH stringByAppendingPathComponent:@"OTHERS/cc"] toPath:[PATH stringByAppendingPathComponent:@"cc"] error:nil];

十四 归档

字符串归档

归档就是把任何对象转化为NSData数据的过程

NSString * str = @"我是将要被归档的字符串";
NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding];

把转化得来的二进制数据持久化

[data writeToFile:PATH atomically:YES];

解析字符串

NSData * data = [[NSData alloc] initWithContentsOfFile:PATH];

字符串解归档

把二进制文件转化成对应对象格式

NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);

 [str release];
 [data release];

归档

归档前,先要建文件夹

LNBClass * class = [[LNBClass alloc] init];
BOOL isDir;
NSFileManager * fileManager = [NSFileManager defaultManager];
[fileManager fileExistsAtPath:[PATH stringByAppendingPathComponent:@"USER"] isDirectory:&isDir];
if (isDir == NO) {
      //不存在,创建文件夹
  fileManager createDirectoryAtPath:[PATH stringByAppendingPathComponent:@"USER"] withIntermediateDirectories:YES attributes:nil error:nil];
}

1.需要遵从NSCoding协议的对象,都要实现协议里的方法
2.开始归档
(1)可变的空NSData对象

NSMutableData * data = [[NSMutableData alloc] init];

(2)归档工具

NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

(3)归档

[archiver encodeObject:class forKey:@"class"];

(4)关闭归档工具

[archiver finishEncoding];

(5)把Data对象持久化

[data writeToFile:PATH atomically:YES];

(6)释放对象

[data release];
[archiver release];
[class release];

解归档

(1)把要解归档的文件读成NSData

NSData * data = [[NSData alloc] initWithContentsOfFile:PATH];

(2)解归档工具

NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

(3)解归档

LNBClass * class = [[unarchiver decodeObjectForKey:@"class"] retain];

【此处要retain】

(4)关闭解归档工具

[unarchiver finishDecoding];

(5)释放对象

[data release];
[unarchiver release];
[class showAllStudents];
[class release];

十五,JSON解析

获取二进制数据
解析之前,必须了解数据格式

NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://10.0.8.8/sns/my/user_list.php?number=20&page=2"]];

进行JSON格式解析

NSError * error = nil;
NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (error != nil) {
    NSLog(@"%@", error);
}

【JSON解析一定要知道,你解析的数据里面存的是啥】

十六,文件句柄

读文件

 //获取到文件的读句柄,就可以通过读句柄,读取该文件的内容
 NSFileHandle * handle = [NSFileHandle fileHandleForReadingAtPath:PATH];

常用方法

 readDataToEndOfFile 
 readDataOfLength

定位到某个字节

 seekToFileOffset     
 readDataOfLength

写句柄

获取到文件的写句柄,就可以对该文件进行写操作

 NSFileHandle * hanle = [NSFileHandlefileHandleForWritingAtPath:PATH];
 NSString * str = @"写入我吧";
 [hanle seekToEndOfFile];
 [hanle writeData:data];NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding];

清空文件至剩余参数个字节

 truncateFileAtOffset

十七,XML解析

获取待解析数据

 NSData * data = [[NSData alloc] initWithContentsOfFile:PATH];

获取节点树

 NSError * error = nil;
 GDataXMLDocument * doc = [[GDataXMLDocument alloc] initWithData:data options:0 error:&error];
 if (error != nil) {
 NSLog(@"%@",error)

获取根节点

 GDataXMLElement * rootElement = doc.rootElement;

获取books节点

 GDataXMLElement * booksElement = [rootElement elementsForName:@"books"][0];

获取book节点

 GDataXMLElement * bookElemtnt = [booksElement elementsForName:@"book"][0];

 NSArray * bookArray = [doc nodesForXPath:@"//books/book[@language = 'en' ]" error:nil][0];

Xpath语法,能够快速定位一个节点
“//”表示忽略前面的节点名,直接取节点名为book的节点
Xpath可以进行数据按照属性进行筛选

 GDataXMLElement * bookElement = [doc nodesForXPath:@"//books/book[@language = 'ch']" error:nil][0];

获取属性的值

 GDataXMLNode * languageNode = [bookElement attributeForName:@"language"];
 NSString * language =languageNode.stringValue;
 NSLog(@"%@",language);

获取auther

 GDataXMLElement * authorElement = [bookElement elementsForName:@"auther"][0];

获取name节点

 GDataXMLElement * nameElement = [authorElement elementsForName:@"name"][0];
 NSString * authorName = [nameElement stringValue];
 NSLog(@"%@",authorName);


 [doc release];
 [data release];
    原文作者:刘奇1993
    原文地址: https://www.jianshu.com/p/c33ba10ed07f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞