Ios UIViewController将不会被删除
我正在努力解决两个UIViewController之间的保留问题。视图控制器从未被删除,导致我的应用程序内存消耗不断增加 UITitleScreenViewController是我的初始视图控制器。当我从它转到UIChooseAntViewController a choose player屏幕时,我想放弃对UIITleviewController的所有权,但正如您在下面的仪器中看到的那样,控制器在转换后仍然保留: 第二个图像是保留/释放历史记录。133之前的所有条目都是在应用程序启动时发布的。我相信133对和140对是由故事板segue创造的。那么,谁的责任是发布额外的释放来销毁控制器呢?我试图在我的遗嘱上设置self.view=nil,但没有达成协议 它不仅没有释放控制器,而且每次转换时都会创建控制器的新实例。例如,当我从ChooseAnt返回到Title时,它会创建另一个UITitleViewController实例 重要的是要说: 1目标方案中未勾选NSZombies标志 2我的UITitleViewController中没有任何块,我在UIChooseAntController中注释掉了所有块。事实上,这些控制器非常简单。Utitle完全是通过故事板定义的,只是一个带有背景的视图和两个执行序列的按钮 而UIChooseAnt是一个控件,它提供背景和滑动界面来显示可用字符和单选按钮。通过调用[self-PerformsgueWithIdentifier]以编程方式执行segue 3我不知道这是否重要,但分段被定义为模态,没有动画 编辑:4没有一个控制器相互引用 下面是TitleViewController的源代码 这个问题快把我逼疯了。如果有人能解释一下的话。任何事情都会有很大的帮助!谢谢Ios UIViewController将不会被删除,ios,objective-c,memory-management,uiviewcontroller,Ios,Objective C,Memory Management,Uiviewcontroller,我正在努力解决两个UIViewController之间的保留问题。视图控制器从未被删除,导致我的应用程序内存消耗不断增加 UITitleScreenViewController是我的初始视图控制器。当我从它转到UIChooseAntViewController a choose player屏幕时,我想放弃对UIITleviewController的所有权,但正如您在下面的仪器中看到的那样,控制器在转换后仍然保留: 第二个图像是保留/释放历史记录。133之前的所有条目都是在应用程序启动时发布的。
@interface SMTitleScreenViewController ()
@property (weak, nonatomic) IBOutlet UIButton *buttonPlay;
@property (weak, nonatomic) IBOutlet UIButton *buttonCamera;
- (IBAction)onButtonPlay:(id)sender;
- (IBAction)onButtonCamera:(id)sender;
@end
@implementation SMTitleScreenViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIColor* color = [UIColor colorWithRed:0.2509f green:0.1176f blue:0.0745f alpha:1.0f];
UIFont* font = [UIFont fontWithName:@"Jungle Roar" size:BUTTON_FONT_SIZE];
NSString* playString = NSLocalizedString(@"Play", @"");
NSString* cameraString = NSLocalizedString(@"Camera", @"");
[self.buttonPlay setTitle:playString forState:UIControlStateNormal];
[self.buttonPlay setTitle:playString forState:UIControlStateHighlighted];
[self.buttonPlay setTitleColor:color forState:UIControlStateNormal];
[self.buttonPlay setTitleColor:color forState:UIControlStateHighlighted];
self.buttonPlay.titleLabel.font = font;
[self.buttonCamera setTitle:cameraString forState:UIControlStateNormal];
[self.buttonCamera setTitle:cameraString forState:UIControlStateHighlighted];
[self.buttonCamera setTitleColor:color forState:UIControlStateNormal];
[self.buttonCamera setTitleColor:color forState:UIControlStateHighlighted];
self.buttonCamera.titleLabel.font = font;
}
- (void) viewDidDisappear:(BOOL)animated
{
if ([self.view window] == nil)
{
self.view = nil;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if ([self.view window] == nil)
{
self.view = nil;
}
}
- (IBAction)onButtonPlay:(id)sender
{
}
- (IBAction)onButtonCamera:(id)sender
{
}
编辑:UIChooseAntViewController(根据请求)
@interface SMChooseAntViewController ()
@property (strong, nonatomic) UIImageView* rope;
@property (strong, nonatomic) UIImageView* antFrontLayer;
@property (strong, nonatomic) UIImageView* antBackLayer;
@property (strong, nonatomic) NSArray* antFrontImages;
@property (strong, nonatomic) NSArray* antBackImages;
@property (strong, nonatomic) NSArray* antNameImages;
@property (strong, nonatomic) UIButton* leftButton;
@property (strong, nonatomic) UIButton* rightButton;
@property (strong, nonatomic) UIButton* confirmButton;
@property (nonatomic) NSUInteger selectedAntID;
@property (strong, nonatomic) UIImage* radioImageHighlighted;
@property (strong, nonatomic) UIImage* radioImage;
@property (strong, nonatomic) NSMutableArray* radioViews;
@property (weak, nonatomic) IBOutlet UILabel *antDescriptionLabel;
@property (weak, nonatomic) IBOutlet UIImageView *antDescriptionBG;
@property (strong, nonatomic) UIImageView* antNameView;
@property (strong, nonatomic) UISwipeGestureRecognizer* leftSwipeRecognizer;
@property (strong, nonatomic) UISwipeGestureRecognizer* rightSwipeRecognizer;
- (void) onArrowButton:(id)sender;
- (void) onConfirmButton:(id)sender;
- (void) respondToSwipe:(UISwipeGestureRecognizer*)recognizer;
@end
@implementation SMChooseAntViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
// Needed to come in between front and back player image layers
UIImage* ropeImage = [UIImage imageNamed:ROPE_IMAGE_PATH];
self.rope = [[UIImageView alloc] initWithImage:ropeImage];
self.rope.center = CGPointMake(screenSize.width / 2.0f, ropeImage.size.height / 2.0f);
UIColor* brownColor = [UIColor colorWithRed:0.2509f green:0.1176f blue:0.0745f alpha:1.0f];
self.antDescriptionLabel.textColor = brownColor;
self.antDescriptionLabel.numberOfLines = 0;
NSArray* antNames = [SMProfile antNames];
// Cache available Player Views in a NSArray
UIImage* frontImages[MAX_AVAILABLE_ANTS];
UIImage* backImages[MAX_AVAILABLE_ANTS];
UIImage* nameImages[MAX_AVAILABLE_ANTS];
for (NSUInteger i = 0; i < MAX_AVAILABLE_ANTS; ++i)
{
NSString* antName = [antNames objectAtIndex:i];
frontImages[i] = [SMImage imageNamed:[NSString stringWithFormat:@"%@_title_front.png", antName]];
backImages[i] = [SMImage imageNamed:[NSString stringWithFormat:@"%@_title_back.png", antName]];
nameImages[i] = [SMImage imageNamed:[NSString stringWithFormat:@"%@_name.png", antName]];
}
self.antFrontImages = [NSArray arrayWithObjects:frontImages[0], frontImages[1], frontImages[2], nil];
self.antBackImages = [NSArray arrayWithObjects:backImages[0], backImages[1], backImages[2], nil];
self.antNameImages = [NSArray arrayWithObjects:nameImages[0], nameImages[1], nameImages[2], nil];
// Load Selected player from profile
SMProfile* profile = [SMProfile mainProfile];
self.selectedAntID = profile.antID.unsignedIntegerValue;
self.antFrontLayer = [[UIImageView alloc] initWithImage:[self.antFrontImages objectAtIndex:self.selectedAntID]];
self.antBackLayer = [[UIImageView alloc] initWithImage:[self.antBackImages objectAtIndex:self.selectedAntID]];
self.antNameView = [[UIImageView alloc] initWithImage:[self.antNameImages objectAtIndex:self.selectedAntID]];
self.antNameView.center = CGPointMake(screenSize.width / 2.0f, self.antDescriptionBG.frame.origin.y);
NSString* antDescriptionKey = [NSString stringWithFormat:@"AntDescription%lu", (unsigned long)self.selectedAntID];
self.antDescriptionLabel.text = NSLocalizedString(antDescriptionKey, @"");
self.antDescriptionLabel.numberOfLines = 0;
self.antDescriptionLabel.adjustsFontSizeToFitWidth = YES;
self.antFrontLayer.center = CGPointMake(screenSize.width / 2.0f, ropeImage.size.height * 0.75f);
self.antBackLayer.center = self.antFrontLayer.center;
// Here a perform button creation, loading and positioning
// No blocks are being called
// add Target to buttons
[self.leftButton addTarget:self action:@selector(onArrowButton:) forControlEvents:UIControlEventTouchUpInside];
[self.rightButton addTarget:self action:@selector(onArrowButton:) forControlEvents:UIControlEventTouchUpInside];
[self.confirmButton addTarget:self action:@selector(onConfirmButton:) forControlEvents:UIControlEventTouchUpInside];
// Create and configure SwipeRecognizers
self.leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(respondToSwipe:)];
self.leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:self.leftSwipeRecognizer];
self.rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(respondToSwipe:)];
self.rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:self.rightSwipeRecognizer];
// Here a create a custom page control scheme. I load two radio button images
// create views and add them to the root view node.
// Add remaining view to the hierarchy
[self.view addSubview:self.antBackLayer];
[self.view addSubview:self.rope];
[self.view addSubview:self.antFrontLayer];
[self.view addSubview:self.confirmButton];
[self.view bringSubviewToFront:self.antDescriptionBG];
[self.view bringSubviewToFront:self.antDescriptionLabel];
[self.view addSubview:self.leftButton];
[self.view addSubview:self.rightButton];
[self.view addSubview:self.antNameView];
[self.view bringSubviewToFront:[self.radioViews objectAtIndex:0]];
}
- (void) viewDidDisappear:(BOOL)animated
{
if ([self.view window] == nil)
{
self.rope = nil;
self.antFrontLayer = nil;
self.antBackLayer = nil;
self.antFrontImages = nil;
self.antBackImages = nil;
self.antNameImages = nil;
self.leftButton = nil;
self.rightButton = nil;
self.confirmButton = nil;
self.radioImageHighlighted = nil;
self.radioImage = nil;
self.radioViews = nil;
self.antNameView = nil;
self.leftSwipeRecognizer = nil;
self.rightSwipeRecognizer = nil;
self.view = nil;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if ([self.view window] == nil)
{
self.view = nil;
}
}
- (void)onArrowButton:(id)sender
{
UIButton* button = (UIButton*)sender;
NSInteger direction = button.tag;
// if on boundaries do nothing (first ant selected and swipe left or last ant selected and swipe right)
if ((self.selectedAntID == 0 && direction == -1) || (self.selectedAntID == (MAX_AVAILABLE_ANTS - 1) && direction == 1))
{
return;
}
// Update Radio Buttons. Unselect previous and select next.
UIImageView* currRadio = [self.radioViews objectAtIndex:self.selectedAntID];
currRadio.image = self.radioImage;
self.selectedAntID = (self.selectedAntID + MAX_AVAILABLE_ANTS + direction) % MAX_AVAILABLE_ANTS;
UIImageView* nextRadio = [self.radioViews objectAtIndex:self.selectedAntID];
nextRadio.image = self.radioImageHighlighted;
self.antFrontLayer.image = [self.antFrontImages objectAtIndex:self.selectedAntID];
self.antBackLayer.image = [self.antBackImages objectAtIndex:self.selectedAntID];
self.antNameView.image = [self.antNameImages objectAtIndex:self.selectedAntID];
// here I was issuing some block to perform the swipe animation for the ant image views. I commented them and I'm just replacing the images now (3 lines above)
}
- (void)onConfirmButton:(id)sender
{
// Save player choice to profile and perform segue
SMProfile* profile = [SMProfile mainProfile];
profile.antID = [NSNumber numberWithUnsignedInt:self.selectedAntID];
[profile save];
[self performSegueWithIdentifier:@"chooseAntToStageSelect" sender:self];
}
- (void) respondToSwipe:(UISwipeGestureRecognizer *)recognizer
{
// forward swipe to onArrowButton message
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft)
{
[self onArrowButton:self.rightButton];
}
else if (recognizer.direction == UISwipeGestureRecognizerDirectionRight)
{
[self onArrowButton:self.leftButton];
}
}
@end
当从A显示B视图控制器时,A不会释放,因为A是presentingViewController请参阅sdk文档
或者,如果A、B是导航控制器的子视图控制器,则A存储在推送堆栈中,推送到B时,该堆栈不会被删除。您将视图控制器推送到堆栈中,因此,直到最后一个视图控制器未弹出,控制器才会被释放 要深入了解对孩子的依赖,请阅读下面的文章 我相信这会有帮助的
您是否在UITitleScreenViewController中创建了任何UIChooseAntViewController属性?没有。实际上我忘了提到这一点。没有一个控制器相互引用。UITitleScreenViewController代码已按原样发布。能否发布uIChooseAntViewController的代码??我认为你保留了那里的任何对象,因此它不是releasedOk,我只是将它添加到原始帖子中。我对几个部分进行了注释,以使其更小。谢谢你看。丹云谢谢你的领导。看起来这正是发生的事情,UIChooseAntViewController通过其modalParentViewController属性持有对title controller的引用,而UITitle持有一个modalChild,尽管我仍然不知道如何修复它。可能我使用了错误的转换。我不希望这些视图被堆叠,我希望它们彼此完全独立。比如,当我从菜单转到游戏屏幕时。我想释放所有与菜单相关的资源并加载游戏资源。我该怎么做?谢谢?你可以这样做:第1步:显示目标视图控制器B。第2步:当A消失时,A将B设置为当前窗口的根视图控制器。看起来这正是发生的事情。正如我所指的丹云,我需要从一种观点过渡到另一种观点,并且在这两者之间不保持任何关系。我该怎么做?