- 同志们根据题目这些就是我平时 不太清楚的 我相信很多人也是不清楚的 所以我打算把他们弄明白了 为了给大家分享一下 自己做个笔记
- weak 和strong的区别:
weak:弱饮用。
strong :强引用。
我自己写了一个例子可以说明他们的区别:
@interface ViewController ()
@property (strong, nonatomic) myView *testView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
myView *testView = [[myView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
testView.backgroundColor = [UIColor redColor];
[self.view addSubview:testView];
self.testView = testView;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"点击了界面了");
[self.testView removeFromSuperview];
NSLog(@"self.testView 的内存地址 %p",self.testView);
}
@end
#import "myView.h"
@implementation myView
-(void)dealloc{
NSLog(@"已经被销毁了");
}
@end
然后打印的结果是:
可以看到 对象并没有销毁,下面用weak我们看一下的结果:
可以清楚的看到 对象销毁了,这说明强引用的对象在被移除的时候是没有完全移除的,内存地址中还保留着一块内存,只不过该内存地址指向的是空。
在举一个例子 ,我是引用别人的:
可以看到weak 在对象引用完毕就销毁了。他俩的区别暂时先说到这 ,后面的还有相应的介绍。
-
delagate 为什么用weak 那为什么不用strong呢?
我们一般写delegate 这样写:
然后我们一般在调用她的地方是这样写的
self.delegate = self;
假如delegate 用strong修饰的话 那是不是就会导致循环引用了(self 强引用delegate ,delegate又指向了self),所以用weak了。
-
string为什么用copy?为什么很多时候不用strong呢?
下面我用一个例子进行说明:
可以看到 用strong引用的话 会导致出现此类的问题
如果我们换了copy:
可以看到 copy 解决了这个问题
那么我们如果换成weak呢:
总结:copy主要是为了防止mutablecopy改变影响到自己,作用是为了安全。其实数组也是这个道理,但是数组我们经常用strong ,虽然mutablearray也是array的子类 但是我们很少会直接付值给他 所以也就不存在这种情况了,所以我们经常用strong在数组中 ,记住:string是可以用strong的 如果我们没有上述说的情况就可以。只不过我们为了安全性考虑用copy 更好些。
- __block 我们在block中要改变外部某一个变量时,为什么必须的加上__block 才可以改 ,难道是因为语法吗?
如果不加上__block的结果,可以看到我会报语法错误大致的意思是不能改,如果加上了__block就可以修改了,为什么呢?
我们可以将我们的oc的代码转换成c++文件来看下,使用命令:
clang -rewrite-objc 源代码文件名
看到的结果是:
可以看到一个局部变量加上__block之后 就会变成与block 一样的结构体,也就是报我们的成员变量拿到地址进行传递过去 ,这样的话block内部就能够修改了。
-
@dynamic 和 @synthesize
@synthesize 是:告诉编辑器在编译的时候主动生成setter 和getter 方法,如果自定义了setter 和getter 方法那么将会覆盖。
@dynamic:是告诉编辑器不生成setter 和getter 方法,由程序员自己手动创建。如果你没有创建setter 和getter 方法编译时候不会报错,在运行的时候会报错。如果这两一个一个都没有写 默认就是@synthesize var = _var;
下面说一下俩的区别:
可以看到他俩的区别
其实@dynamic最常用的地方实在coredata中,编译的时候不用生成setter 和getter 方法在运行的时候开始调用 由coredata框架自动分配。 - 深浅copy
深copy:不但复制对象本身 还复制他的内存地址
浅copy:只复制对象本身
举一个例子:比如不可变的字符串 如果深拷贝的话 改变当前的字符串新生成的字符串的值也会改变,浅拷贝的话新生成的字符串的值不会改变。
规律:1.本身对象是可变的 那么无论mutablecopy 还是copy 都是深拷贝。
2.本身对象是不可变的 ,mutablecopy是深拷贝,copy是浅拷贝。 -
blcok的循环引用解释
为什么会造成循环引用:block内部会对外部强引用调用block产生强引用(这句话不知道怎么说了,语文不好),block内部会对外部弱引用调用block产生弱引用。
这就是造成循环引用的原因。
举几个例子什么情况下会出现循环引用:
不调用deallloc方法
这就是:block内部会对外部强引用调用block产生强引用
如果我换成:weak
这就是:block内部会对外部弱引用调用block产生弱引用
特殊著名的两种情况:
1.block里边不能用下划线(_)给大家看一个结果
发现还是内存泄漏了,所以不能使用下划线
还有一种情况:
这种是不会内存泄露的 因为我们self 没有强引用他
给大家说一下 @strongify(self) 和单纯的weakSelf那个好
@strongify(self):我没有倒入rac的那个框架,所以我给他说下为什么好
实际上 我们想要的结果是我们想三秒过后打印我们想要的结果,用weakself 是不行的 用@strongify 可以解决的
其实 rac中的@weakify 和 @strongify就是这个道理 。所以我们平时的那个weakself - delegate 和 通知的区别
区别一 :delegate 有返回值,通知没有返回值 。
区别二 :delegate 只能“单对单” 通知可以“一对多”,一个通知可以 发了 整个app可以同时接到通知 ,但是delegate就不行 在同一时刻只能完成一个响应的方法的实现。
区别三:delegate 我们一般都是层级不是很深的情况使用,通知可以很深的层级(比如你可以从首页跳转到你app 很深的层级)。 -
new 和 alloc init的区别
可以看到 他们两个基本没有什么区别,alloc 把关联的对象分配到相邻的内存区域内,减少内存的消耗。而new的初始化方法只能是init,相对来讲alloc 更好一些。
-
block 使用
1.blcok的语法,我在网上找个图片
2.blcok作为属性使用
myView.h文件
#import <UIKit/UIKit.h>
@interface myView : UIView
@property (copy, nonatomic) void (^myBlock)(int x,int y);
@end
myView.m文件
#import "myView.h"
@implementation myView
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if (self.myBlock) {
self.myBlock(10, 10);
}
}
@end
ViewController.m文件
#import "ViewController.h"
#import "myView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
myView *obtainView = [[[NSBundle mainBundle]loadNibNamed:@"myView" owner:nil options:nil] lastObject];
obtainView.frame = CGRectMake(0, 100, self.view.frame.size.width, 200);
obtainView.myBlock = ^(int x, int y) {
int sum = x + y;
NSLog(@"�%d",sum);
};
[self.view addSubview:obtainView];
}
3.block 作为参数进行传递,最常见的是我们封装网络请求 或者写工具类的时候(这之前是我封装网络请求部分的代码)
例如:
[weakSelf.manager POST:[weakSelf configUrl:weakSelf.requestUrl] parameters:weakSelf.paramDic constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
[formData appendPartWithFileData:weakSelf.fileData name:weakSelf.name fileName:weakSelf.fileName mimeType:weakSelf.mimeType];
} progress:^(NSProgress * _Nonnull uploadProgress) {
CGFloat progress = 1.0 * uploadProgress.completedUnitCount/uploadProgress.totalUnitCount;
weakSelf.progress = progress;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[weakSelf detailSuccess:responseObject complete:complete];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[weakSelf detailError:error complete:complete];
}];
4.blcok可以全局利用(个人理解),倒入头文件全局可以用
例如:
typedef void(^buttonBlock)(int a,int b);
@interface ViewController : UIViewController
@end
5.在方法中调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
buttonAction();
}
void (^buttonAction)() = ^{
NSLog(@"大哥我开始在里边执行方法了");
};
解释:这里为什么没写:if(buttonAction){buttonAction() };因为blcok我们确定是一定存在的 所以我们没有必要这样写,像1中如果不写if,那么我们在点击myview的时候就会crash。
6.作为函数的返回值(最常用的就是Masonry)作用就是:连式编程
- (MASConstraint * (^)(id attr))mas_equalTo;
- (MASConstraint * (^)(id))equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
// 实现链式编程
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler
make.left.equalTo(superview.mas_left).with.offset(padding.left);
make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];
-至此我们只是了解blcok的简单使用,更深层次的理解以及使用 我可能写不好了,我找了一篇文章 大家一起进步
block深入理解