第一次写博客,完全不知道如何写,就把随堂笔记都写到这上面吧。
Objective-c在c语言上做了拓展
cocoa touch触摸用户体验
主力框架OC及Swift,C/C++可以混合到代码里
底层思维
抽象思维
“时空人”
时间分析:编译compile时-运行run时
空间分析:变量放在-内存上(栈stack和堆heap)
区别非常大,决定变量生存周期--比如内存泄漏
人物分析:编译器会添油加醋
开发方式
Clang或gcc命令行 适合调试研究微观的探查
Xcode项目
#import可以避免多次引用的重复冲突
@autoreleasepool自动释放池
NSlog与printf不同多一个@不在引号内 多了日期时间
oc的文件是.m
命令行与linux上的命令基本相似
-fobjc-arc开关语句/开关命令支持了arc的内存引用技术管理 该机制对内存管理影响大
-o output输出 后跟文件名
clang -help命令手册
Xcode项目 构建正规工程项目 使用大型框架,追求设计质量和代码组织
1.Creat a new Xcode project
2.OS X→Application→Command Line Tool
3.******名字
4.选择目录
5.main.m
6.build&run
GCC古老的编译器可以跨平台 开源
LLVM low level virtual machine
optimizer优化器
Code Generator代码生成器
Programming with Objective-C必读文档
苹果官方文档:https://developer.apple.com/library/
Programming with Objective-C
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/
ios专区https://developer.apple.com/library/ios/
苹果开发者大会WWDC
https://developer.apple.com/videos/wwdc/2015
本节课代码
#import
int main(int argc, const * argv[])
{
@autoreleasepool
{
NSlog(@"Hello,world!");
}
return 0;
}
类型系统
值类型value type(c语言)
·基础数值类型
·结构struct
·枚举enum
引用类型reference type
·类class(面向对象)
·指针pointer
·块block
类型装饰
·协议protocol
·类别category
·扩展extension
接口文件rpoint.h
@interface RPoint:NSObject继承
@property int x;定义一个属性 类似c中的字段
@property int y;//状态 里面放了数据成员
-(void) print;//行为
@end
实现文件
#import
#import"rpoint.h"
@implementation RPoint
-(void)print{
NSlog(@"[%d,%d]",self.x,self.y);//self表示当前的对象
}
@end
//创建对象
RPoint* rp1=[[RPoint alloc] init];//RPoint是一个类型,rp1是一个实例,alloc是向系统请求分配内存的一个过程,加中括号是方法或消息的调用;init=initialize初始化,会调用默认构造器,会把x,y初始化成0;该语句是动态的向系统请求内存分配
typedef struct{//结构里面不能写类里面像print之类的方法
int x;
int y;
}SPoint;
[rp1 print];//给rp1发送一个print的消息
SPoint sp1;//自动分配内存,结构对应的实例,叫做值
rp1可以发消息,sp1不可以,可见RPoint有一个面向对象的特征
变量在哪---画运行时的内存图
rp1栈上存储指针,0x00588系统随机分配,指向的堆上面的对象,访问对象需通过指针访问
sp1在栈上直接存储了值
栈stack
·无ARC(自动引用基数)负担,由系统自动管理,以执行函数为单位
·空间大小编译时确定(参数+局部变量)
·函数执行时,系统会自动分配一个stack
·函数执行结束,系统会立即自动回收或销毁stack
·函数之间通过拷贝值传递
·具有局部性,大小有限额,一般就几M,超出会产生一个stack overflow,一般栈不会溢出,除非写成死循环或超大递归
堆heap
·分配由程序员手动请求(创建对象时)
·释放有两种机制,用的较多时ARC自动释放(确定时)
·函数之间通过拷贝引用(指针)传递
·具有全局性,总体无大小限制(受制于系统内存整体大小)
堆是最自由也是最不容易出问题的--内存泄露
栈的负担很清,堆需要程序员操心的
RPoint* rp2=rp1//拷贝
rp2.x++;
rp2.y++; //rp1的堆值也会改变
SPoint sp2=sp1;//拷贝
sp2.x++;
sp2.y++;//sp1的值不变
传参 本质上就是拷贝
void process(*rp3,sp3);
传参调用完毕,process栈会被回收
数据成员-属性与实际变量
成员扮演类的**功能非常重要的角色
数据成员data member描述对象状态
·实例变量instance variable对内的
·属性property对外的
函数成员function member描述对象行为
·方法method
·初始化器init
·析构器dealloc
人识属性
·属性表达的是实例的状态,描述的是类型的对外接口,
编译器回为属性定义生成三种构造
·一个getter访问器方法
·一个setter访问器方法
·一个实例变量
访问器方法
[employee setFirstName: @"Tom"];
NSlog(@"First Name: %@",[employee firstName]);
属性表达式(点表达式)=访问器方法
employee.LastName=@"Chen";
NSlog(@"Last Name: %@",employee.lastName);
employee.age=32;对象,只能访问实例属性
Employee.max=400;类,可以访问类属性(模拟出来的).max=setmax
//employee._tempCount=100;类外不可以访问实例变量,类外只能访问属性
@synthesize
更改的不是属性的名字,是属性后对应的实例变量名字
如果自定义了getter和setter访问器方法,或针对只读属性定义了getter访问器方法,编译器将不再合成实例变量
属性是公有的 类外
实例变量是私有的 类内
在类外一律使用属性来访问,类内大多也通过self使用属性访问,只有以下情况使用实例变量来访问://生存周期非常独特
·初始化器init
·析构器dealloc
·自定义访问器方法
实例变量的生存周期
·实例变量的存储,跟随对象实例存储在堆上
·值类型实例变量直接“内嵌”在对象实例中,跟随对象实例内存释放而被释放
·引用类型实例变量通过指针“引用”堆上的引用类型实例,ARC针对引用进行计数管理,自动释放引用计数为0的对象
属性的描述特性(Attribute)
·读写属性readwrite
·只读属性readonly
·多线程特性
·原子性atomic //要么完成,要么彻底不执行,不会被其他线程抢走
·非原子性nonatomic
·内存管理特性
·ARC环境
·强引用strong//可能出现循环引用,并导致内存泄露,
·弱引用weak//防止循环引用
·拷贝属性copy创建独立拷贝
函数成员
全局函数(c语言)
NSlog c风格的全局函数
成员函数(ObjC方法)
都是代码段上的可执行序列
方法是类的成员函数,表达实力行为或类型行为。
减号代表实例方法 返回值用括弧扩起来
-(void) print;
-(BOOL) isEqualToPoint:(BLNPoint*) point;//方法名称后跟的冒号,后面是参数
-(void) moveToX:(int)x toY:(int)y; //多个参数
加号是类型方法
函数实现里面的大括号,即方法体
所有方法默认为公有方法。没有private或protected方法
实现私有方法的小技巧
接口文件不用方法,实现文件放方法
动态消息分发:(由于)方法调用通过运行时动态消息分发实现,(所以)在对象上调用方法,又称向对象发送消息
实例方法--表达实例行为,只可以通过实例调用
类方法--表达类型行为,只能通过类型调用
实例属性用self.来访问
了解编译器背后对实例方法
void print(BLNPoint* self){
NSlog("")
}
[p1 print];//print(p1);
面向对象的思维方式
对象+行为//传统的结构化编程:算法+结构
类方法里可以用self
不可以self.x=100;是指针。。。不表示实例
可以[self process];//等同于[BLNPoint Process];是类
+(void) process{
NSLog(@"process...");
}
BLNPoint* origin=[BLNPoint getOriginPoint];
//BLNPoint* origin=getOriginPoint();C语言全局变量形式
如果参数类型为值类型,则为传值方式:如果参数类型引用类型,则为传指针方式
方法可以没哟参数,也可以没有返回值
如果方法有参数,方法名约定包涵第一个参数名(只需要内部参数),从第二个参数开始需要显示提供外部参数名
动态方法调用机制
灰色部分有一部分是指针,指着class
有性能负担
初始化器和析构器
对象初始化器:-(id) init可以重载多个
类型初始化器:+(void)initalize只能有一个
对象析构器:-(void)dealloc只能有一个
没有类型析构器
初始化对象实例时,init通常和alloc搭配使用
alloc是类方法
查看类库 按住command键 点击鼠标
alloc所做的事情--NSObject以实现:
·在堆上分配合适大小的内存
·将属性或者实例变量的内存置0.(指针为0)
init所做的事情--可以用系统合成的也可以自定义:
·调用父类初始化器配[super init]//前置调用
·初始化当前对象实例变量//注意使用实例变量,不要使用属性
new相当于 调用alloc/init的无参数版
~类初始化器
·类初始化器initialize负责类型级别的初始化
·initialize在每个类使用之前被系统自动调用,且每个进程周期中,只被调用一次
·子类的initialize会制动调用父类的initialize//前置调用
1.自动调用:ARC对对象属性的引用技术减持
2.手工实现
NSLog(@"ads");
非内存资源,非托管资源,需手工关闭
3.自动调用:父类dealloc后置
dealloc由ARC根据对象引用计数规则,在释放对象内存前自动调用,无法手工调用。
面向对象
封装encapsulation
继承inheritance
一个类型在另外类型基础上新型扩展实现
多态polymorphism
不同类型针对同一行为接口的不同实现方式
继承到底继承了什么?
·实例变量
·属性
·实例方法//(初始化器和析构器是特殊的实例方法)
·类方法
大写的是类 小写的是对象
NSObject是所有类的根类,祖先类
按住option经常看NSObject帮助文档
继承的两层含义:
·成员复用:子类复用基类成员
·类型抽象:将子类当作父类来使用(is-a关系准则)子类可以使用父类成员
私有的成员也是都被继承的
子类只是访问不到
多态
运行时多态
子类在父类统一行为接口下,表现不同的实现方式
//override重写
//Shape是声明类型
//Rectangle是实际类型
[shape draw];//多态调用
[rect draw];//多态调用:函数地址的动态辨析,效率较低
[rect print];//多态调用
子类重写父类同名同参数方法:子类只可以重写父类方法
方法名相同、参数不同:OC不支持方法的重载
在子类代码中。可以使用super来调用基类的实现。
·self具有多态性,可以指向不同子类
·super没有多态性,仅指向父类
~继承中的init和dealloc
初始化器init
·子类自动继承基类的初始化器
·子类也可以重写基类初始化器,此时子类初始化器必须首先调用基类的一个初始化器(手工调用)
析构器dealloc
·子类可以选择继承基类析构器,或者重写基类析构器
·子类析构器执行完毕后,会自动调用基类析构器(后置调用,且不支持手工调用)
·子类析构器自动具有多态性
Tips:尽量避免在父类init和dealloc中调用子类重写方法