1

助けてください。私のアプリはほぼ完成しています。現在、最適化の過程にあるため、Instrument Allocations ツールを使用しており、View Controller に問題がありますが、メモリの理由がわかりません。メインビューからdetailedViewControllerに移動するたびに増加します。

問題と思われるコード部分は次のとおりです。

  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

// Create and push a detail view controller.

    self.entriesDetailedViewController = [[EntriesDetailedViewController alloc]init];

Entry *selectedEntry = (Entry *)[[self fetchedResultsController] objectAtIndexPath:indexPath];

self.entriesDetailedViewController.entry = selectedEntry;

[self.navigationController pushViewController:self.entriesDetailedViewController animated:YES];
[self.entriesDetailedViewController release];
}

以下は、detailedViewController.h のコードです。

  #import <UIKit/UIKit.h>


  @class Entry;

 @interface EntriesDetailedViewController : UIViewController <UITextViewDelegate> {

//IBOutlet UIButton *createEntryButton;
IBOutlet UITextField *entryTextField1;
IBOutlet UITextView *entryTextField2;
IBOutlet UIBarButtonItem *textbodyBarButton;
IBOutlet UIBarButtonItem * catLabel;
IBOutlet UINavigationBar *entryNameToolBar;
IBOutlet UINavigationBar *textBodyToolBar;
IBOutlet UIImageView *reviewCheck;
IBOutlet UIImageView *textBackground;
IBOutlet UIBarButtonItem *reviewButton;
BOOL isChecked;

NSManagedObjectContext *managedObjectContext;


Entry *entry;

    }


 @property (nonatomic,retain) IBOutlet UITextField *entryTextField1;
 @property (nonatomic,retain) IBOutlet UITextView *entryTextField2;
 @property (nonatomic,retain) IBOutlet UIBarButtonItem *textbodyBarButton;
 @property (nonatomic,retain) IBOutlet UIBarButtonItem *catLabel;
 @property (nonatomic,retain) IBOutlet UINavigationBar *entryNameToolBar;
 @property (nonatomic,retain) IBOutlet UINavigationBar *textBodyToolBar;
 @property (nonatomic,retain) IBOutlet UIImageView *reviewCheck;
 @property (nonatomic,retain) IBOutlet UIBarButtonItem *reviewButton;
 @property BOOL isChecked;
 @property (nonatomic,retain) IBOutlet UIImageView *textBackground;

 @property (nonatomic,retain) NSManagedObjectContext *managedObjectContext;
 @property (nonatomic, retain) Entry *entry;


 - (void)setUpUndoManager;
 - (void)cleanUpUndoManager;
 - (void)textViewDidBeginEditing:(UITextView *)entryTextField2;
 - (void)textViewDidEndEditing:(UITextView  *)entryTextField2;
 - (void)saveContext;



 - (IBAction)dismisskeyboard;
 - (IBAction)dismissKeyboardfromTextView;
 - (IBAction) selectReview;


 @end

そして、これは detailedViewController.m です:

  #import "EntriesDetailedViewController.h"
  #import "Entry.h"
  #import "TheLearningMachineAppDelegate.h"


  @implementation EntriesDetailedViewController

  @synthesize entryTextField1,entryTextField2,textbodyBarButton,managedObjectContext,catLabel, entryNameToolBar,textBodyToolBar, reviewCheck,reviewButton,isChecked,textBackground, entry, undoManager;


  #pragma mark -
  #pragma mark View lifecycle


  - (void)viewWillAppear:(BOOL)animated {

  }

  - (void)viewDidLoad {
      [super viewDidLoad];

  // Configure the title, title bar, and table view.

      self.title = @"Consultation";

    UIBarButtonItem *rightButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(save:)]; 
self.navigationItem.rightBarButtonItem = rightButton; 
[rightButton release];

[self setUpUndoManager];

self.entryTextField1.text = self.entry.entryname;
self.entryTextField2.font = [UIFont fontWithName:@"Helvetica" size:17.0];
self.entryTextField2.text = self.entry.textbody;
self.catLabel.title = self.entry.category;
[self.entryTextField2 setFrame:CGRectMake(24, 56, 273, 140)];

self.textBackground.image = [UIImage imageNamed:@"alert_background.png"];
[self.textBackground setFrame:CGRectMake(0,46,312,140)];



  //Initializing a kind of checkBox button

if ([self.entry.active boolValue] == YES) {

    self.reviewCheck.image = [UIImage imageNamed:@"checkedwhitesquare.png"];

    self.isChecked = YES;
}

else {

    self.reviewCheck.image = [UIImage imageNamed:@"UncheckedWhiteSquare.png"];

    self.isChecked = NO;

}

  }


  - (IBAction) selectReview {

      if (isChecked==NO){
        self.reviewCheck.image = [UIImage imageNamed:@"checkedwhitesquare.png"];
    self.isChecked = YES;
    [self.entry setValue:[NSNumber numberWithBool:YES] forKey:@"active"];
    [self performSelector: @selector(save:)];

}
else {

    self.reviewCheck.image = [UIImage imageNamed:@"UncheckedWhiteSquare.png"];

    self.isChecked = NO;
    [self.entry setValue:[NSNumber numberWithBool:YES] forKey:@"active"];
    [self performSelector: @selector(save:)];

}

  }



  - (void)textViewDidBeginEditing:(UITextView  *)entryTextField2{
[self.navigationController setNavigationBarHidden:YES animated:YES];
self.entryNameToolBar.hidden =YES; 
self.textBodyToolBar.hidden =NO;
self.textbodyBarButton.style =UIBarButtonItemStyleBordered;
self.textbodyBarButton.title =@"Terminer la saisie";
[self.entryTextField2 setFrame:CGRectMake(24, 50, 273, 140)];
[self.textBackground setFrame:CGRectMake(0,46,312,140)];
  }

  - (IBAction)textViewDidEndEditing: (UITextView  *)entryTextField2{
      [self.navigationController setNavigationBarHidden:NO animated:YES];
      self.entryNameToolBar.hidden =NO;
      self.textBodyToolBar.hidden =YES;
      [self.entryTextField2 setFrame:CGRectMake(24, 50, 273, 140)];
      [self.textBackground setFrame:CGRectMake(0,46,312,140)];
      self.textbodyBarButton.style =UIBarButtonItemStyleDone;
      self.textbodyBarButton.title =@"Corps de texte";  

  }

  - (IBAction)dismisskeyboard{

[self.entryTextField1 resignFirstResponder];
  }

  - (IBAction)dismissKeyboardfromTextView{

[self.entryTextField2 resignFirstResponder];

  }

  - (void)saveContext {

      NSError *error = nil;
      if (self.managedObjectContext != nil) {
          if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Erreur" 
        message:@"blabla" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];


        abort();

          } 
      }
  }  


  - (IBAction)save:(id)sender {

      // if there's text in textfield1 and textfield2 and a category has been set 
      if (([self.entryTextField1.text length]!= 0) && ([self.entryTextField2.text length]!= 0) && ([self.catLabel.title length]!= 0)){ 

    [self.entry setValue:self.entryTextField1.text forKey:@"entryname"];
    [self.entry setValue:self.entryTextField2.text forKey:@"textbody"];
    [self.entry setValue:self.catLabel.title forKey:@"category"];

    if (self.isChecked == YES) {
        [self.entry setValue:[NSNumber numberWithBool:YES]forKey:@"active"];
    }
    else {

        [self.entry setValue:[NSNumber numberWithBool:NO] forKey:@"active"];
    }

    [self.entry setValue:[NSNumber numberWithBool:NO] forKey:@"editable"];

    //save
    NSError *error;
    [self.managedObjectContext save:&error];
    [self saveContext];

    //Return to mainview
    [self.navigationController popViewControllerAnimated:YES];
    [self.entry release];
    //self.entry =nil;
}

else {

    if([self.entryTextField1.text length] ==0){

        UIAlertView *alert =[[UIAlertView alloc] 
                             initWithTitle:@"Oooops..." 
                             message:@"Your entry has no name" 
                             delegate:nil 
                             cancelButtonTitle: @"ok" 
                             otherButtonTitles:nil];
        [alert show];
        [alert release];

    }
    else {

        if ([self.entryTextField2.text length]==0){

            UIAlertView *alert =[[UIAlertView alloc] initWithTitle:@"Oooops..." message:@"Your list is empty" delegate:nil cancelButtonTitle: @"ok" otherButtonTitles:nil];
            [alert show];
            [alert release];

        }
        else {

            if ([self.catLabel.title length]==0){

                UIAlertView *alert =[[UIAlertView alloc] initWithTitle:@"Oooops..." message:@"You need to choose a category for this list first." delegate:nil cancelButtonTitle: @"ok" otherButtonTitles:nil];
                [alert show];
                [alert release];

                  }
              }

          }
      }
   }


  - (void)setEditing {
  //    [super setEditing:editing animated:animated];
  }




  #pragma mark -
  #pragma mark Undo support

  - (void)setUpUndoManager {

    if (self.entry.managedObjectContext.undoManager == nil) {

    NSUndoManager *undoMgr = [[NSUndoManager alloc] init];
    [undoMgr setLevelsOfUndo:1];
    self.entry.managedObjectContext.undoManager = undoMgr;
    [undoMgr release];


    }

    // Register as an observer of the entry's context's undo manager.
    NSUndoManager *entryUndoManager = self.entry.managedObjectContext.undoManager;
NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
    [dnc addObserver:self selector:@selector(undoManagerDidUndo:) name:NSUndoManagerDidUndoChangeNotification object:entryUndoManager];
    [dnc addObserver:self selector:@selector(undoManagerDidRedo:) name:NSUndoManagerDidRedoChangeNotification object:entryUndoManager];


  }


  - (void)cleanUpUndoManager {

      // Remove self as an observer.
      [[NSNotificationCenter defaultCenter] removeObserver:self];

      if (self.entry.managedObjectContext.undoManager == undoManager) {
          self.entry.managedObjectContext.undoManager = nil;
          self.undoManager = nil;
      }       
  }


  - (NSUndoManager *)undoManager {
      return self.entry.managedObjectContext.undoManager;
  }


  - (void)undoManagerDidUndo:(NSNotification *)notification {

  }


  - (void)undoManagerDidRedo:(NSNotification *)notification {

  }

  - (BOOL)canBecomeFirstResponder {
      return YES;
  }


  - (void)viewDidAppear:(BOOL)animated {
      [super viewDidAppear:animated];
      [self becomeFirstResponder];
  }


  - (void)viewWillDisappear:(BOOL)animated {
      [super viewWillDisappear:animated];
      [self resignFirstResponder];
  }

- (void)viewDidUnload {

// Release any properties that are loaded in viewDidLoad or can be recreated lazily.


self.entryTextField1 =nil;
self.entryTextField2 = nil;
self.catLabel = nil;
self.entryNameToolBar = nil;
self.textBodyToolBar = nil;
self.reviewCheck = nil;
self.textBackground = nil;
self.reviewButton = nil;
self.entry = nil;
self.navigationItem.rightBarButtonItem = nil;
[self cleanUpUndoManager];
self.entry.managedObjectContext.undoManager = nil;


}

  - (void)dealloc {

[entryTextField1 release], entryTextField1 = nil;
[entryTextField2 release], entryTextField2 = nil;
[catLabel release], catLabel = nil;
[entryNameToolBar release], entryNameToolBar = nil;
[textBodyToolBar release], textBodyToolBar = nil;
[reviewCheck release], reviewCheck = nil;
[textBackground release], textBackground = nil;
[reviewButton release], reviewButton = nil;
[self cleanUpUndoManager];
[entry.managedObjectContext.undoManager release],  
     entry.managedObjectContext.undoManager = nil;
[entry release],entry = nil;
[managedObjectContext release];


[super dealloc];
}

申し訳ありませんが、これは私が知っている長いコードですが、途方に暮れています。私を助けてください。

皆さんが提案したように、私は次の変更を行いました:

また、コードの viewDidUnload と Dealloc の部分を次のように変更しました。

release + nil の概念も、dealloc での [self.object release] と [object release] の呼び出しと、viewDidUnload での self.object = nil の呼び出しの違いもよくわかりません。

4

4 に答える 4

1

新しいEntriesDetailedViewController. 解放しても記憶は戻らないということですか?で何かを正しくリリースしていない可能性があります-[EntriesDetailedViewController dealloc]

EntriesDetailedViewController毎回新しいものを生成するのではなく、最初に必要になったときに作成し、 setEntry:. ビュー コントローラーを保持するように ivar を既に設定しています。それを利用してもいいでしょう。

于 2011-03-17T17:11:39.777 に答える
0

投稿したコードからは原因は明らかではありませんが、Instruments は各割り当てがどこで行われたかを示しているので、追跡するのは難しくありません。

于 2011-03-17T17:12:01.057 に答える
0

dealloc では次の形式を使用する必要があります。

[entryTextField1 release], entryTextField1 = nil;

このフォームを使用して設定する必要があります (例viewDidUnload: ):

self.entryTextField1 = nil;

静的分析を実行すると、さらにいくつかの問題が検出されるはずです。それらを修正します。

すべて修正したら、アプリを再実行します。(100%のカバー率ではないと思います)

また、必ずバージョン管理を使用してください。多くの問題を突き止めていることに気付くでしょう - それらがすべて整理されるまで、途中でさらに多くの問題/クラッシュが予想されるはずです.

残念ながら、メモリの問題を永久に回避することはできません。適切なメモリ管理を同時に学習しながら、そのうちのいくつかを追跡するのは困難です (つまり、難しい方法です)。幸運を!

于 2011-03-17T20:34:21.083 に答える
0

ねえねえ、あなたは何人を知っていますか?今知りました!!!!!!!! 私はなんて愚かなのでしょう... entryDetailedViewController.h ファイルを注意深く調べると、宣言されている textbodyBarButton があることがわかります... まあ、それはリリースされていませんでした、私はそれを忘れていました...

では、お時間をロスさせて申し訳ありません。

私はちょうど追加しました:

    self.textbodyBarButton = nil;
[textbodyBarButton release];

rootViewController に戻ると、すべてのメモリが解放されます。

ですから、ある日同じ問題を抱えているとしたら、それはそれと同じくらい愚かなことかもしれません. .h ファイルで宣言した内容を 2 回確認してください。

うわー、それに3日費やしたけど…

大変お待たせいたしました。ご辛抱いただきありがとうございました。

于 2011-03-20T18:33:35.653 に答える