2021-07-12-16学习文档
OC语法
命令行编译(Clang编译器)
终端编译 :Clang -fobjc-arc 文件 -o
编译器-内存管理 -o输出 输出文件
内存
内存模型: 引用类型 class pointer block 值类型 struct enum
栈:存储值类型,以执行函数为单位,一个函数一个栈。空间大小编译时决定。执行结束时立即销毁
函数之间通过拷贝值传递( 两个变量独立存在)
栈的结构简单,有push和pop就可以。内存上只需要维护栈末端的指正即可。处理一些时效性不强、临时性的代码。栈看做一个交换临时数据的内存区域。在多线程上,栈的线程是独有的,所以不需要考虑线程的安全。
堆:存储引用类型对象
函数之间通过拷贝引用(指针)传递(两个变量的值为同一值
在堆上进行内存分配的时候,需要锁定堆上能够容纳存放对象的空闲块,主要为了线程安全,我们需要对这些空闲块进行锁定和同步
堆是完全二叉树,即除最底层节点外都是填满的。swift的堆是通过双向链实现的。由于堆可以retain和release,所以很容易使分配空间不连续。采用链表的目的是希望能够将内存连起来。在release时通过调整链表指针来整合空间。
swift引入了可以保存额外信息的side table,让对象的弱引用先指向其对应的side table这样做的好处是,在僵尸对象长期占用内存的情况下,不再需要保留“僵尸”对象,取而代之的只是保留引用计数器和指向原对象指针内存占用非常小的side table。
weak strong copy assign
weak比assign多一个功能,当对象消失后,会自动把指针变为nil,内存引用计数为0,发送消息就不会导致野指针
strong在修饰block的时候就相当于copy,而retain修饰block的时候就相当于assign;strong存放在堆中;retain存放在栈中;
使用retain,它的生命周期会随着函数的结束而出栈的,就会让block出现提前被释放掉的危险。
强引用也就是我们通常所讲的引用,其存亡直接决定了所指对象的存亡。 弱引用除了不决定对象的存亡外,其他与强引用相同。即使一个对象被持有无数个若引用,只要没有强引用指向他,那么其还是会被清除。
id类型
OC:万能指针,能指向操作任何OC对象。id类型支持方法的动态调用。
swift:Swift有一种AnyObject类型,用来代表某个对象。它和Objective-C中的id类型很相似。Swift把id导入为AnyObject,使你能够在编写类型安全的Swift代码的同时,保留不确定类型对象(untyped object)的灵活性。
拷贝写法、重写
_name = [name copy];
OC重写不用写 swift 的override 但也要写 [super xxxx] delloc不能写super alloc
swift具有多态性,可以指向不同子类 super没有多态性,仅指向当前父类
OC不支持重载
报错 -(void)moveToX: (int) x toY:(int)y;
-(void)moveToX:(double)x toY:(double)y;
== 避免在父类init和delloc中调用子类重写的方法==
NSString、NSMutableString
NSString是否相等 [str1 isEqualToString:str2];
NSString 更改字符串就是更改内存地址 str1=[str1 stringByAppendingString:@" Yes!"];
NSMutableString
NSMutableString
NSMutableString *mustr2 = [NSMutableString stringWithString: @"Hello,World!"];
估计近似的缓存容量值
stringWithCapacity:100
[mustr3 appendString:@"Hello Objective"];
[mustr3 insertString:@"-C" atIndex:mustr3.length];
[mustr3 setString:@"Hi Objective"];
NSRange replaceRange = NSMakeRange(0, 2);
[mustr3 replaceCharactersInRange:replaceRange withString:@"Hello"];
NSRange deleteRange = NSMakeRange(5, 10);
[mustr3 deleteCharactersInRange:deleteRange];
NSArray数组
NSArray数组
NSArray *array3=@[@"Shanghai",@"Beijing",@"New York",@"Paris"];
最后一个不需要加nil 其余都要
NSArray只能存对象类型
NSNull* nullValue=[NSNull null]; NSNumber *numberObject1= [NSNumber numberWithInteger:number ];//使用
NSNumber将NSInteger包装为对象
指针指向内部的可以更改
快速枚举 直接访问内存,优化索引检查
for ( BLNPoint* point in array5)
{
point.x++;
point.y++;
}
//迭代器模式
NSEnumerator *enumerator = [array5 objectEnumerator];
BLNPoint* item;
while (item = [enumerator nextObject])
{
item.x++;
item.y++;
}
For 循环
数组查找索引
NSUInteger index1=[array5 indexOfObject:target]; //查找相等值
要重写
- (BOOL)isEqual:(id)anObject{
if (! [anObject isKindOfClass: [BLNPoint class]] ){
return false;
}
BLNPoint* other=anObject;
return (self.x==other.x && self.y==other.y);
}
指针是否相等
NSUInteger index2=[array5 indexOfObjectIdenticalTo:p3]; //查找
NSMutableArray
//修改元素
[muArray1 addObject:p5]; //添加元素
[muArray1 removeObjectAtIndex:2]; //删除元素
[muArray1 insertObject:p6 atIndex:1]; //某位置添加元素
muArray1[0]=p7; //置换元素
arrayWithCapacity 预估容量
Set 存储对象不能重复
NSDictionary 表
NSDictionary *dictionary1 = @{ //前面是key后面是value
@"Shanghai" : p1,
@"Beijing" : p2,
@"New York" : p3,
@"Paris" : p4};
NSMutableDictionary *dictionary2 = [NSMutableDictionary dictionaryWithObjectsAndKeys:
//前面是value后面是key
p1,@"Shanghai",
p2,@"Beijing",
p3,@"New York",
p4,@"Paris",
nil];
protocol
swift的protocol和OC的protocol 相同的构造方法,但不声明方法的使用
OC的protocol可以声明变量 swift 不能
OC的protocol变量要在实现类的.h文件声明
@optional 协议的方法的可选 底下默认全部都是可选方法
直到遇到@require 默认必选
OC内存优化
图片的加载方式
//就算指向它的指针被销毁,该资源也不会被内存中干掉
放在Asset.xcassets的图片,默认就有缓存(图片经常被使用)
UIImage *img = [UIImage imageNamed:<#(nonnull NSString *)#>];
//指向它的指针被销毁,该资源会被内存中干掉
不经常用放在项目中的图片就不带有缓存(图片不经常用,大批量的图片)
NSString *imagePath = [[NSBundle mainBundle] pathForResource:<#(nullable NSString *)#> ofType:<#(nullable NSString *)#>];
UIImage * sourceImg = [UIImage imageWithContentsOfFile:<#(nonnull NSString *)#>];
-(NSArray *)dataArr{
if (_dataArr == nil) {
self.dataArr = @[@{},
@{},
@{}];
}
return _dataArr;
}
OC函数库使用
UIAlertController
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"输入有误" message:@"请输入第一个数" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"我知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"点击确认");
}];
[alert addAction:defaultAction];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alert animated:YES completion:nil];
动画
//动画关键帧
[UIView animateKeyframesWithDuration:1 delay:1 options:UIViewKeyframeAnimationOptionCalculationModeCubicPaced animations:^{
CGRect frame = self.animationView.frame;
frame.origin.y += 50;
self.animationView.frame = frame;
} completion:^(BOOL finished) {
self.animationView.backgroundColor = UIColor.greenColor;
}];
//动画执行
[UIView animateWithDuration:1 delay:1 options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = self.animationView.frame;
frame.origin.y += 50;
self.animationView.frame = frame;
} completion:^(BOOL finished) {
self.animationView.backgroundColor = UIColor.blueColor;
}];
延迟方法
self performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>
xib使用
如果view从xib加载,就会调用initWithCoder,不会调用init 和 initwithframe
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
<#statements#>
}
return self;
}
//从xib唤醒,添加xib控件的子控件,控件的更改
-(void)awakeFromNib{
[super awakeFromNib];
UIToolbar *toolBar = [[UIToolbar alloc]init];
[self.shopImage addSubview:toolBar];
self.toolBar = toolBar;
}
//初始化 让所有的view都执行方法
// for (UIImageView *imageView in self.scrollView.subviews){
// [imageView removeFromSuperview];
// }
[self.scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
自动布局
代码编写:
//伸缩化 向左向上对齐
redView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleTopMargin;
添加约束
删除约束
同级view布局
中心点布局
KVC使用
键值编码,就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态地访问和修改对象的属性。而不是在编译时确定。
通常情况下,KVC不允许你要在调用setValue:属性值 forKey:(或者keyPath)时对非对象传递一个nil的值。很简单,因为值类型是不能为nil的。如果你不小心传了,KVC会调用setNilValueForKey:方法。
通常情况下,KVC不允许你要在调用setValue:属性值 forKey:(或者keyPath)时对不存在的key进行操作。
不然,会报错forUndefinedKey发生崩溃,重写forUndefinedKey方法避免崩溃。
KVC可以动态更改系统控件私有属性的样式
[self.pageControl setValue:[UIImage imageNamed:@"3"] forKeyPath:@"preferredIndicatorImage"];
取出数组中所有模型的某个属性值
Person *person3 = [[Person alloc]init];
person3.name = @"e";
person3.age = @16;
NSArray *allPersons = @[person1, person2, person3];
NSArray *allPersonName = [allPersons valueForKey:@"name"];
NSLog(@"%@", allPersonName);
因为 Swift中的 Optional 机制,所以 valueForKey方法返回的是一个 Optional 值,我们还需要对返回值做一次解包处理,才能得到实际的属性值。
class Person {
var name:String = ""
init(name:String){
self.name = name
}
}
let p2 = Person(name:"lichangan")
let nameKeyPath = \Person.name
let name = p2[keyPath:nameKeyPath]
print(name) //lichangan
p2[keyPath:nameKeyPath] = "shuaige"
print(p2.name) //shuaigei
MVP
相对MVC而言, M:Model多了网络请求, C:VC负责的逻辑处理传给protocol和presender执行 P:persender继承protocol调用方法。VC调用persender的函数。 persender一般继承NSObject
View都一样。