在我TextViewTableViewCell
,我有一个变量来跟踪块和一个配置方法,其中传入和分配块.
这是我的TextViewTableViewCell
班级:
//
// TextViewTableViewCell.swift
//
import UIKit
class TextViewTableViewCell: UITableViewCell, UITextViewDelegate {
@IBOutlet var textView : UITextView
var onTextViewEditClosure : ((text : String) -> Void)?
func configure(#text: String?, onTextEdit : ((text : String) -> Void)) {
onTextViewEditClosure = onTextEdit
textView.delegate = self
textView.text = text
}
// #pragma mark - Text View Delegate
func textViewDidEndEditing(textView: UITextView!) {
if onTextViewEditClosure {
onTextViewEditClosure!(text: textView.text)
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我在我的cellForRowAtIndexPath
方法中使用configure方法时,如何在我传入的块中正确使用弱自我.
这是我没有弱自我的情况:
let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell …
Run Code Online (Sandbox Code Playgroud) 我用的NSTimer
是这样的:
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:@selector(tick) userInfo:nil repeats:YES];
Run Code Online (Sandbox Code Playgroud)
当然,NSTimer
保留了创建保留周期的目标.此外,self
不是一个UIViewController所以我没有任何东西viewDidUnload
,我可以无效的计时器来打破循环.所以我想知道我是否可以使用弱引用:
__weak id weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];
Run Code Online (Sandbox Code Playgroud)
我听说计时器必须无效(我想从运行循环中释放它).但我们可以在我们的dealloc中做到这一点,对吗?
- (void) dealloc {
[timer invalidate];
}
Run Code Online (Sandbox Code Playgroud)
这是一个可行的选择吗?我已经看到人们处理这个问题的方法很多,但我还没有看到这个.
假设我们有三个对象:祖父母,父母和孩子.祖父母保留父母,父母保留孩子,孩子保留父母.祖父母释放父母.
在这种情况下会发生什么?
memory-management objective-c ios automatic-ref-counting retain-cycle
我读了很多关于__weak self
在里面使用的帖子dispatch_async
,现在我有点困惑.
如果我有 :
self.myQueue = dispatch_queue_create("com.biview.core_data", NULL);
dispatch_async(self.myQueue, ^(void){
if (!self.var1) {
self.var1 = ...;
}
dispatch_async(dispatch_get_main_queue(), ^(void) {
if ([self.var2 superview]) {
[self.var2 removeFromSuperview];
}
[self.Label setText:text];
});
});
Run Code Online (Sandbox Code Playgroud)
我需要使用吗__weak self
?因为我读过在某些情况下dispatch_async
不需要__weak self
.
假设我已经创建了一个弱自我使用
__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
...
}];
Run Code Online (Sandbox Code Playgroud)
在该块内,如果我嵌套另一个块:
[weakSelf doAnotherBlockOperation:^{
[weakSelf doSomething];
}
Run Code Online (Sandbox Code Playgroud)
它会创建一个保留周期吗?我是否需要为weakSelf创建另一个弱引用?
__weak typeof(self) weakerSelf = weakSelf;
[weakSelf doAnotherBlockOperation:^{
[weakerSelf doSomething];
}
Run Code Online (Sandbox Code Playgroud) memory-management block ios automatic-ref-counting retain-cycle
假设我在UIViewController
子类中有以下方法:
- (void)makeAsyncNetworkCall
{
[self.networkService performAsyncNetworkCallWithCompletion:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicatorView stopAnimating];
}
});
}];
}
Run Code Online (Sandbox Code Playgroud)
我知道self
块内部的引用导致UIViewController
实例被块保留.只要performAsyncNetworkCallWithCompletion
不将块存储在我的属性(或ivar)中NetworkService
,我是否认为没有保留周期?
我意识到上面的这个结构将导致UIViewController被保留直到performAsyncNetworkCallWithCompletion
完成,即使它是由系统早先发布的.但它可能(甚至可能吗?),系统会收回我的UIViewController
所有(更改到iOS 6的一个管理方式后UIViewController
的后盾CALayer
内存)?
如果有理由我必须做"弱自我/强自我舞蹈",它看起来像这样:
- (void)makeAsyncNetworkCall
{
__weak typeof(self) weakSelf = self;
[self.networkService performAsyncNetworkCallWithCompletion:^{
typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
[strongSelf.activityIndicatorView stopAnimating];
}
});
}];
}
Run Code Online (Sandbox Code Playgroud)
但是我觉得这很难看,并且如果没有必要就想避免它.
objective-c uiviewcontroller ios objective-c-blocks retain-cycle
我们是否需要在UIAnimation块中使用__weak self,如下所示?如果我们不指定自我弱,是否会产生保留周期问题?
[UIView animateWithDuration:animationDuration
delay:0
options:UIViewAnimationCurveEaseInOut
animations:^{
[self doSomething];
} completion:^(BOOL finished) {
if (finished) {
[self doSomething];
}
}];
Run Code Online (Sandbox Code Playgroud)
我也对以下场景感到困惑.有什么想法吗?请分享您的意见.
[self.navController dismissViewControllerAnimated:animated
completion:^{
[self doSomething];
}];
Run Code Online (Sandbox Code Playgroud)
我们应该在这里使用弱者吗?
EDIT2:
不.建议的答案是关于异步调用.我想要并需要同步调用,就像在普通的标准递归调用中一样.
编辑:
而
__unsafe_unretained void (^unsafe_apply)(UIView *, NSInteger) ;
Run Code Online (Sandbox Code Playgroud)
在没有警告或错误的情况下编译,它在运行时失败,并将NULL存储到unsafe_apply中.
不过这个:
- (void) applyToView: (UIView *) view {
UIColor * (^colorForIndex)(NSInteger) = ^(NSInteger index) {
return [UIColor colorWithHue: ((CGFloat) index / 255.0f)
saturation: 0.5f
brightness: 0.5f
alpha: 1.0f] ;
} ;
void (^applyColors) (UIView *, NSInteger index) = ^(UIView * view, NSInteger index) {
view.backgroundColor = colorForIndex(index) ;
} ;
void (^__block recurse_apply)(UIView *, NSInteger) ;
void (^apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) { …
Run Code Online (Sandbox Code Playgroud) recursion objective-c objective-c-blocks automatic-ref-counting retain-cycle
我需要阻止.但编译器会发出警告
"在这个区块强势捕捉'自我'可能会导致保留周期"
__weak typeof(self) weakSelf = self;
[generalInstaImage setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:data[@"images"][@"low_resolution"][@"url"]]] placeholderImage:[UIImage imageNamed:@"Default"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
NSLog(@"success");
[generalInstaImage setImage: image];
[weakSelf saveImage:generalInstaImage.image withName:data[@"id"]];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(@"fail");
}];
Run Code Online (Sandbox Code Playgroud)
我尝试编写类似的例子weakSelf.generalInstaImage
,但编译器生成错误而不编译.
objective-c ios objective-c-blocks automatic-ref-counting retain-cycle
假设我们在Core Data模型中有两个实体:Departments和Employees.
该部门与员工有一对多的关系.
我有以下ManagedObjectContexts:
- Root:连接到持久性存储协调器
- Main:具有父Root的上下文
当我想创建一个Employee我做到以下几点:
-我有一个部门的主要方面
-我在主环境中创建一个Employee
-我分配部门到员工的部门属性
-我省主要方面
-我保存根上下文
这将在Main上下文和Root上下文中创建一个保留周期.
如果我没有子上下文(所有在Root上下文中)这样做,那么我可以通过调用refreshObject:mergeChanges
Employee 来打破保留周期.在我使用这两个上下文的情况下,我仍然可以使用该方法来打破Main上下文的循环,但是我如何打破Root上下文的循环呢?
旁注:这是一个描述我的问题的简单示例.在仪器中,我可以清楚地看到分配数量的增长.在我的应用程序中,我的上下文比一个级别更深,导致更大的问题,因为我得到了一个新的实体分配,每个上下文保留周期我正在保存.
更新15/04:NSPrivateQueueConcurrencyType vs NSMainQueueConcurrencyType
保存两个上下文后,我可以refreshObject:mergeChanges
使用Department对象在Main上下文中执行.正如预期的那样,这将使Department对象重新出错,打破保留周期并在该上下文中取消分配Department和Employee实体.
下一步是打破Root上下文中存在的保留周期(保存Main上下文已将实体传播到Root上下文).我可以在这里做同样的技巧,并refreshObject:mergeChanges
在Department对象的Root上下文中使用.
奇怪的是:当NSMainQueueConcurrencyType创建我的根上下文(所有分配重新故障和dealloced)这工作得很好,但与NSPrivateQueueConcurrencyType创建我的根上下文(所有分配的重新出现故障,但不工作不 dealloced ).
附注:Root上下文的所有操作都在performBlock(AndWait)调用中完成
更新15/04:第2部分
当我做另外一个(没用,因为没有改变)保存或回滚与NSPrivateQueueConcurrencyType根上下文,对象似乎被释放.我不明白为什么这与NSMainQueueConcurrencyType的行为不一样.
更新16/04:演示项目
我创建了一个演示项目:http://codegazer.com/code/CoreDataTest.zip
更新21/04:到达那里
感谢Jody Hagings的帮助!
我试图refreshObject:mergeChanges
移出我的ManagedObject didSave
方法.
你能解释一下我之间的区别吗:
[rootContext performBlock:^{
[rootContext save:nil];
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
Run Code Online (Sandbox Code Playgroud)
和
[rootContext performBlock:^{
[rootContext save:nil];
[rootContext performBlock:^{
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
}]; …
Run Code Online (Sandbox Code Playgroud) retain-cycle ×10
ios ×7
objective-c ×5
block ×1
core-data ×1
fault ×1
ios5 ×1
nstimer ×1
recursion ×1
swift ×1