IOS开发之OC学习笔记(上)
2016-03-13 21:41
363 查看
该笔记源自本人对一个网络视频的学习
百度网盘链接 ,密码: tp3a
如有侵权,请联系本人删除。
都是比较基础的OC知识,中高级开发者可以忽略本文
很多重要内容在代码注释中
Student.m
main.m
Person.m
main.m
Student.m部分代码如下
子类GoodStudent可以继承父类Student,子类可以访问父类的成员变量,例如GoodStudent.m:
Student.h代码如下
看下Student.m中的实现
在xcode4.5以后的环境下,可以省略@synthesize,并且默认会去访问_age这个成员变量,如果找不到_age这个成员变量,会自动生成一个叫做_age的私有成员变量,也就是说上面Student.m的实现可以省略。
可以手动实现setter方法,实现对引用对象的动态释放,Student.m中实现如下:
@property可以传递一些参数,其中retain参数可以自动实现上面的setter方法。
@class关键字给我们的编码和代码性能带来一些便利
Sutdent.h中的示例如下:
验证一个实体是否销毁,可以重写dealloc方法
一般情况,我们使用的是autorelease释放内存,使用方法如下
可以使用了静态方法实现一个类的自动release,具体代码如下
main.m中测试代码如下
协议定义的方法不是必须实现的
本文到此结束,下一篇介绍Foundation框架
百度网盘链接 ,密码: tp3a
如有侵权,请联系本人删除。
都是比较基础的OC知识,中高级开发者可以忽略本文
很多重要内容在代码注释中
1. 第一个os程序
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!"); } return 0; }
2. OC 的类
Student.h// Student.h // OC的类 // 只是用来声明Student这个类有哪些成员变量和方法 #import <Foundation/Foundation.h> // @interface代表声明一个类 // : 代表继承 @interface Student : NSObject { // 成员变量要定义在下面的大括号中{} int age; int no; } // 在这里声明的所有方法都是公共 // age的get方法 // - 代表动态方法 + 代表静态方法 - (int)age; // age的set方法 - (void)setAge:(int)newAge; // no的get方法 - (int)no; - (void)setAge:(int)newAge andNo:(int)newNo; @end
Student.m
#import "Student.h" @implementation Student - (int)age { NSLog(@"调用了getAge方法"); return age; } - (void)setAge:(int)newAge { age = newAge; NSLog(@"调用了setAge方法"); } - (int)no { return no; } - (void)setAge:(int)newAge andNo:(int)newNo { age = newAge; no = newNo; } @end
main.m
#import <Foundation/Foundation.h> #import "Student.h" int main(int argc, const char * argv[]) { @autoreleasepool { // 创建一个Student对象: // 1.调用一个静态方法alloc来分配内存 // 暂时把id当做是任何对象 // Student *stu = [Student alloc]; // // // 2.调用一个动态方法init进行初始化 // stu = [stu init]; Student *stu = [[Student alloc] init]; //[stu setAge:100]; //int age = [stu age]; //NSLog(@"age is %i", age); [stu setAge:17 andNo:1]; NSLog(@"age is %i and no is %i", [stu age], [stu no]); // 释放对象 [stu release]; } return 0; }
3. 点语法
Person.h#import <Foundation/Foundation.h> @interface Person : NSObject { int _age; } - (void)setAge:(int)age; // 方法名是setAge: - (int)age; // 方法名是age // 方法名是setAge:andNo: // - (void)setAge:(int)newAge andNo:(int)no; @end
Person.m
#import "Person.h" @implementation Person - (void)setAge:(int)age { NSLog(@"调用了setAge方法:%i", age); _age = age; // 这是错误的写法,会导致死循环,无限调用set方法 // self.age = newAge;// [self setAge:newAge]; } - (int)age { NSLog(@"调用了age方法:%i", _age); return _age; } @end
main.m
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool { Person *person = [[Person alloc] init]; person.age = 10; // 等效于[person setAge:10]; int age = person.age; // 等效于int age = [person age]; NSLog(@"age is %i", age); [person release]; } return 0; }
4. 构造方法、description方法、self使用
在Student.h中加入如下,构造方法// 自己写一个构造方法 - (id)initWithAge:(int)age andNo:(int)no;
Student.m部分代码如下
// 实现构造方法 - (id)initWithAge:(int)age andNo:(int)no { // 首先要调用super的构造方法 // self = [super init]; // 如果self不为nil if (self = [super init]) { // _age = age; // _no = no; self.age = age; self.no = no; } return self; } // 重写父类的description方法 // 当使用%@带打印一个对象的时候,会调用这个方法 - (NSString *)description { NSString *str = [NSString stringWithFormat:@"age is %i and no is %i", self.age, self.no]; //NSString 系统自带的方法,都是自动释放, //不需要[str release],此处可以参见后面内存管理小节 return str; } // 如果直接把方法写在.m文件中,没有在.h文件中进行声明,那么这就是私有方法 // 谁调用方法,self就指向谁 - (void)test { int age = self.age; } + (void)test2 { [Student alloc]; [self alloc]; // 上面两句代码是等效的!! }
子类GoodStudent可以继承父类Student,子类可以访问父类的成员变量,例如GoodStudent.m:
@implementation GoodStudent // 子类访问了父类的成员变量 - (void)test { _age = 10; } @end
5. 关键字new/变量作用域
一下两种写法等价,要记得最后[stu release]
Student *stu = [Student new];
Student *stu = [[Student alloc] init];
Student.h代码如下
#import <Foundation/Foundation.h> @interface Student : NSObject { //public 全局都可以访问 //protected 只能在类内部和子类中访问 //private 只能在类内部访问 // 默认是@protected,一般不用public、private int _age; } - (void)setAge:(int)newAge; - (int)age;
6. @property和@synthesize
Student.h的声明如下,可以看到@property的使用// 当编译器遇到@property时,会自动展开成getter和setter的声明 @property int age; //- (void)setAge:(int)newAge; //- (int)age; //以上两者等效
看下Student.m中的实现
// @synthesize会自动生成getter和setter的实现 // @synthesize默认会去访问跟age同名的变量 // 如果找不到同名的变量,会自动生成一个私有的同名变量age // @synthesize age; // age = _age代表getter和setter会去访问_age这个成员变量 @synthesize age = _age; //- (void)setAge:(int)newAge { // _age = newAge; //} // //- (int)age { // return _age; //}
在xcode4.5以后的环境下,可以省略@synthesize,并且默认会去访问_age这个成员变量,如果找不到_age这个成员变量,会自动生成一个叫做_age的私有成员变量,也就是说上面Student.m的实现可以省略。
7. 内存管理retain、release、autorelease
retain表示对引用对象计数+1;release对引用对象计数-1.Student *stu = [[Student alloc] init]; // 1 // z代表无符号 NSLog(@"count:%zi", [stu retainCount]); [stu retain]; // 2 NSLog(@"count:%zi", [stu retainCount]); [stu release]; // 1 NSLog(@"count:%zi", [stu retainCount]); [stu release]; // 0 // [stu release]; // 如果此处再release,会发生野指针错误,也就是说访问了不属于你的内存
可以手动实现setter方法,实现对引用对象的动态释放,Student.m中实现如下:
// @synthesize book = _book; // 如果自己手动实现了getter和setter,xcode就不会自动生成@synthesize // 也就不会自动生成_book // getter和setter的默认实现 - (void)setBook:(Book *)book { if (_book != book) { // 先释放旧的成员变量 [_book release]; // 再retain新传进来的对象 _book = [book retain]; } }
@property可以传递一些参数,其中retain参数可以自动实现上面的setter方法。
@class关键字给我们的编码和代码性能带来一些便利
Sutdent.h中的示例如下:
// 如果是继承某个类,就要导入类的头文件 // 如果只是定义成员变量、属性,用@class @class Book; @class Card; @interface Student : NSObject // 这里的retain代表:自动在set方法中,release旧值,retain新值 @property (retain) Card *card; // readonly代表只生成get方法的声明 // 默认是readwrite,同时生成get和set方法的声明 @property (readonly) int age; // atomic 就代表给方法进行加锁,保证线程安全,需要消耗大量的资源 @property (atomic) int no; // nonatomic代表方法不需要考虑线程安全问题,适合内存小的移动设备 @property (nonatomic, assign) int no2; // getter是用来指定get方法的方法名 @property (nonatomic, getter = isRich) BOOL rich; @end
验证一个实体是否销毁,可以重写dealloc方法
- (void)dealloc { NSLog(@"%@被销毁了", self); [_book release]; //self.book = nil; [super dealloc]; // 一定要调用super的dealloc方法,而且最好放在最后面调用 }
一般情况,我们使用的是autorelease释放内存,使用方法如下
int main(int argc, const char * argv[]) { // @autoreleasepool代表创建一个自动释放池 @autoreleasepool { Student *stu = [[[Student alloc] init] autorelease]; //Student *stu = [[Student alloc] init]; //[stu autorelease]; } return 0; }
可以使用了静态方法实现一个类的自动release,具体代码如下
+ (id)student { return [[[Student alloc] init] autorelease]; } + (id)studentWithAge:(int)age { // 这里的self指向类名 // Student *stu = [self student]; Student *stu = [Student student]; stu.age = age; return stu; }
8. pragma mark 使用
可以对方法分组标记,使用如下#pragma mark - 公共方法 #pragma mark 读书 - (void)readBook { NSLog(@"当前读的书是:%f", _book.price); }
9. category 使用
在Student+Test.h中增加如下代码,可以实现在不改变Student源码的前提下,对Student经行扩充,甚至可以对系统的NSString等扩充#import "Student.h" // ()代表着是一个分类 // ()中的Test代表着分类的名称 @interface Student (Test) // 分类只能扩展方法,不能增加成员变量 - (void)test2; @end
10. protocol 使用
直接上代码:// Button.h #import <Foundation/Foundation.h> @class Button; // <>代表实现某个协议 @protocol ButtonDelegate <NSObject> - (void)onClick:(Button *)btn; @end @interface Button : NSObject // delegate就是按钮的监听器 @property (nonatomic, retain) id<ButtonDelegate> delegate; // 点击按钮 - (void)click; @end
// Button.m #import "Button.h" @implementation Button - (void)dealloc { [_delegate release]; [super dealloc]; } - (void)click { // respondsToSelector:判断是否实现了某个方法 // 如果_delegate实现了onClick:这个方法 if ( [_delegate respondsToSelector:@selector(onClick:)] ) { // 按钮被点击了,就应该通知监听器.并且告诉监听器哪个按钮被点击了 [_delegate onClick:self]; } else { NSLog(@"监听器并没有实现onClick:方法"); } // conformsToProtocol:判断是否遵守了某个协议 if ([_delegate conformsToProtocol:@protocol(ButtonDelegate)]) { NSLog(@"_delegate 遵守了 ButtonDelegate 这个协议"); } } @end
// ButtonListener.h #import <Foundation/Foundation.h> // 对协议进行提前声明,跟@class的用途是一致的 @protocol ButtonDelegate; @interface ButtonListener : NSObject <ButtonDelegate> @end
// ButtonListener.m #import "ButtonListener.h" #import "Button.h" @implementation ButtonListener - (void)onClick:(Button *)btn { NSLog(@"MyListener已经监听到按钮-%@被点击了", btn); } @end
main.m中测试代码如下
// 初始化一个按钮 Button *button = [[[Button alloc] init] autorelease]; // 初始化一个按钮的监听器 ButtonListener *listener = [[[ButtonListener alloc] init] autorelease]; // 设置按钮的监听器 button.delegate = listener; NSLog(@"button:%@", button); // 点击按钮 [button click];
协议定义的方法不是必须实现的
// Study.h #import <Foundation/Foundation.h> @protocol Study <NSObject> // 默认就是@required - (void)test3; // @required表示必须实现的方法 // 虽然字面上说是必须实现,但是编译器并不强求某个类进行实现 @required - (void)test; - (void)test1; // @optional表示可选(可实现\也可不实现) @optional - (void)test2; @end
11. block 使用
block封装一段代码,可以在任何时候执行,直接上代码// main.m #import <Foundation/Foundation.h> #import "Button.h" typedef int (^MySum) (int, int); void test() { // 定义了一个block,这个block返回值是int类型,接收两个int类型的参数 int (^Sum) (int, int) = ^(int a, int b) { return a + b; }; int a = Sum(10 ,11); NSLog(@"%i", a); } void test2() { // __block有2个下划线 __block int c = 15; // 声明了一个block变量 MySum sum = ^(int a, int b) { // 如果外部的变量用了__block关键字,就可以在block内部修改这个变量 c = 19; // block可以访问外面定义的变量 NSLog(@"c is %i", c); return a + b; }; NSLog(@"%i", sum(10, 10)); } void test3() { // 定义了Sum这种Block类型 typedef int (^Sum) (int, int); // 定义了sump这种指针类型,这种指针是指向函数的 typedef int (*Sump) (int, int); // 定义了一个block变量 Sum sum1 = ^(int a, int b) { return a + b; }; int c = sum1(10, 10); NSLog(@"%i", c); // 定义一个指针变量p指向sum函数 Sump p = sum; // c = (*p)(9, 8); c = p(9, 8); NSLog(@"%i", c); } int main(int argc, const char * argv[]) { @autoreleasepool { Button *btn = [[[Button alloc] init] autorelease]; btn.block = ^(Button *btn) { NSLog(@"按钮-%@被点击了", btn); }; // 模拟按钮点击 [btn click]; } return 0; }
// Button.h #import <Foundation/Foundation.h> @class Button; typedef void (^ButtonBlock) (Button *); @interface Button : NSObject @property (nonatomic, assign) ButtonBlock block; // 模拟按钮点击 - (void)click; @end
// Button.m #import "Button.h" @implementation Button - (void)click { _block(self); } @end
本文到此结束,下一篇介绍Foundation框架
相关文章推荐
- ios核心动画 类图 一目了然
- iOS NSString 和NSData 转换 zhuanzai
- ios cell多选
- ios tableview单选
- iOS开发-进阶:JPush设置标签与别名的API
- iOS开发-进阶:开启Remote notifications
- iOS9 新特征之一:Bitcode
- iOS 学习路线整理(根据学习的深入,需要持续整理)
- iOS视频播放器
- iOS关灯游戏AI的设计和实现
- iOS基础开发练习 国际棋盘 的设计
- iOS之NSDictionary和NSArray以及NSMutableDictionary和NSMutableArray:将不再是问题
- iOS 消息推送
- 支付宝 iOS SDK 的简单使用
- OC基础
- iOS YYText的使用笔记二(YYLabel聊天表情+文字并排)
- iOS 页面传值方式 单例,block,代理协议方法,通知中心
- iOS YYText的使用笔记一(YYTextView图文编辑器)
- 解决iOS打印数组和字典中文显示异常问题
- IOS中如何切换到主线程工作