- 同志們根據題目這些就是我平時 不太清楚的 我相信很多人也是不清楚的 所以我打算把他們弄明白了 為了給大家分享一下 自己做個筆記
- 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 這樣寫:
1.png
然后我們一般在調用她的地方是這樣寫的
self.delegate = self;
假如delegate 用strong修飾的話 那是不是就會導致循環引用了(self 強引用delegate ,delegate又指向了self),所以用weak了。
-
string為什么用copy?為什么很多時候不用strong呢?
下面我用一個例子進行說明:
1.png
可以看到 用strong引用的話 會導致出現此類的問題
如果我們換了copy:
1.png
可以看到 copy 解決了這個問題
那么我們如果換成weak呢:
1.png
總結: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;
下面說一下倆的區別:
image.png
image.png
可以看到他倆的區別
其實@dynamic最常用的地方實在coredata中,編譯的時候不用生成setter 和getter 方法在運行的時候開始調用 由coredata框架自動分配。 - 深淺copy
深copy:不但復制對象本身 還復制他的內存地址
淺copy:只復制對象本身
舉一個例子:比如不可變的字符串 如果深拷貝的話 改變當前的字符串新生成的字符串的值也會改變,淺拷貝的話新生成的字符串的值不會改變。
規律:1.本身對象是可變的 那么無論mutablecopy 還是copy 都是深拷貝。
2.本身對象是不可變的 ,mutablecopy是深拷貝,copy是淺拷貝。 -
blcok的循環引用解釋
為什么會造成循環引用:block內部會對外部強引用調用block產生強引用(這句話不知道怎么說了,語文不好),block內部會對外部弱引用調用block產生弱引用。
這就是造成循環引用的原因。
舉幾個例子什么情況下會出現循環引用:
image.png
image.png
image.png
不調用deallloc方法
這就是:block內部會對外部強引用調用block產生強引用
如果我換成:weak
image.png
這就是:block內部會對外部弱引用調用block產生弱引用
特殊著名的兩種情況:
1.block里邊不能用下劃線(_)給大家看一個結果
image.png
發現還是內存泄漏了,所以不能使用下劃線
還有一種情況:
image.png
這種是不會內存泄露的 因為我們self 沒有強引用他
給大家說一下 @strongify(self) 和單純的weakSelf那個好
@strongify(self):我沒有倒入rac的那個框架,所以我給他說下為什么好
image.png
實際上 我們想要的結果是我們想三秒過后打印我們想要的結果,用weakself 是不行的 用@strongify 可以解決的
image.png
其實 rac中的@weakify 和 @strongify就是這個道理 。所以我們平時的那個weakself - delegate 和 通知的區別
區別一 :delegate 有返回值,通知沒有返回值 。
區別二 :delegate 只能“單對單” 通知可以“一對多”,一個通知可以 發了 整個app可以同時接到通知 ,但是delegate就不行 在同一時刻只能完成一個響應的方法的實現。
區別三:delegate 我們一般都是層級不是很深的情況使用,通知可以很深的層級(比如你可以從首頁跳轉到你app 很深的層級)。 -
new 和 alloc init的區別
image.png
可以看到 他們兩個基本沒有什么區別,alloc 把關聯的對象分配到相鄰的內存區域內,減少內存的消耗。而new的初始化方法只能是init,相對來講alloc 更好一些。
-
block 使用
1.blcok的語法,我在網上找個圖片
image.png
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深入理解