我有一个带有三个ViewControllers(A,B和C)的UITabBarController。在ViewControllerB中,我有一个UIScrollView。 UIScrollView包含我的PhotoViewController的几个实例。这些PhotoViewController对象是从ViewControllerA调用的,而不是它们所在的ViewController B。
PhotoViewController实例有一个UIImage和两个按钮。首先,当我点击我的一个PhotoViewController实例中的按钮时,我收到了“线程1:程序接收信号:”EXC_BAD_ACCESS“'错误。查看stackoverflow时,只要存在内存管理问题,就会出现错误。
由于我是在一个循环中从ViewControllerA中调用的方法创建PhotoViewController对象,并释放这些对象,我想当我切换到ViewControllerB时它们已经被释放 - 因此内存问题。
但这只是我的猜测。你能否告诉我是否应该停止在循环代码中释放PhotoViewController对象?因为这就是我所做的(只是评论说出来)和程序“工作”很好。但是,我仍然不确定这是否是处理它的正确方法,以及它是否会导致未知的内存管理问题。
以下是我的一些代码:
ViewControllerA.m
//在ViewControllerB中创建相册,相册中的照片是PhotoViewController对象
-(IBAction)showAlbum:(UIButton *)sender
{
//Go goes here to get an album and display it in the UIScrollView
albumID = @"ALBUM_ID";
NSString* graphUrl = [NSString stringWithFormat:@"%@/photos?limit=10", albumID];
[_facebook requestWithGraphPath:graphUrl andDelegate:self];
}
...
- (void)request:(FBRequest *)request didLoad:(id)result {
//Code for array of photos
NSLog(@"%@",result);
NSString *requestType = [request.url stringByReplacingOccurrencesOfString:@"https://graph.facebook.com/" withString:@""];
if ([requestType isEqualToString:[NSString stringWithFormat:@"%@/photos?limit=10", albumID]]){
NSArray *photoAlbumArray=(NSArray*)[result valueForKey:@"data"];
[self.label setText:[NSString stringWithFormat:@"%i", [photoAlbumArray count]]];
for(UIViewController *controller in self.tabBarController.viewControllers)
{
if([controller isKindOfClass:[ViewControllerB class]])
{
ViewControllerB *mtbvc = (ViewControllerB *)controller;
[mtbvc setArray:photoAlbumArray];
self.tabBarController.selectedIndex = 1;//switch over to the second view to see if it worked
}
}
}
...
@end
ViewControllerB.m
//循环我创建PhotoViewController对象
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
arrayCount = [array count];
scroller.delegate=self;
scroller.pagingEnabled=YES;
scroller.directionalLockEnabled=YES;
scroller.showsHorizontalScrollIndicator=NO;
scroller.showsVerticalScrollIndicator=NO;
//should have an array of photo objects and the number of objects, correct?
scrollWidth = 0;
scroller.contentSize=CGSizeMake(arrayCount*scroller.frame.size.width, scroller.frame.size.height);
for (int i = 0; i < arrayCount;i++) {
PhotoViewController *pvc = [[PhotoViewController alloc] initWithNibName:@"PhotoViewController" bundle:nil];
UIImageView *scrollImageView = [[UIImageView alloc] initWithFrame:CGRectOffset(scroller.bounds, scrollWidth, 0)];
CGRect rect = scrollImageView.frame;
pvc.view.frame = rect;
[pvc view];
pvc.label.textColor = [UIColor whiteColor];
id individualPhoto = [array objectAtIndex:i];
NSLog(@"%@",individualPhoto);
NSArray *keys=[individualPhoto allKeys];
NSLog(@"%@",keys);
NSString *imageURL=[individualPhoto objectForKey:@"source"];
//here you can use this imageURL to get image-data and display it in imageView
NSURL *url = [NSURL URLWithString:imageURL];
NSData *data = [NSData dataWithContentsOfURL:url];
pvc.imageView.image = [[UIImage alloc] initWithData:data];
pvc.label.text = [individualPhoto objectForKey:@"id"];
//check to make sure the proper URL was passed
//I have an imageView next to the UIScrollView to test whether that works - it does.
[scroller addSubview:pvc.view];
[scrollImageView release];
//[pvc release];
scrollWidth += scroller.frame.size.width;
}
if (arrayCount > 3) {
pageControl.numberOfPages=3;
} else {
pageControl.numberOfPages=arrayCount;
}
pageControl.currentPage=0;
//[self.view addSubview:scroller];
}
PhotoViewController.m
#import "PhotoViewController.h"
@implementation PhotoViewController
@synthesize label, imageView;
-(IBAction)likeButton:(UIButton *)sender
{
//code goes here
for(UIViewController *controller in self.tabBarController.viewControllers)
{
if([controller isKindOfClass:[DemoAppViewController class]])
{
DemoAppViewController *davc = (DemoAppViewController *)controller;
[davc likePicture:self.label.text];
}
}
self.tabBarController.selectedIndex = 0;//switch over to the third view to see if it worked
}
-(IBAction)skipButton:(UIButton *)sender
{
//code goes here
}
-(IBAction)likeCommentButton:(UIButton *)sender
{
//code goes here
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end
PhotoViewController.h
#import <UIKit/UIKit.h>
#import "DemoAppViewController.h"
#import "MyTabBarViewController.h"
@interface PhotoViewController : UIViewController {
IBOutlet UILabel *label;
IBOutlet UIImageView *imageView;
UIButton *likeButton;
UIButton *skipButton;
UIButton *likeCommentButton;
}
@property (nonatomic, retain) UILabel *label;
@property (nonatomic, retain) UIImageView *imageView;
-(IBAction)likeButton:(UIButton *)sender;
-(IBAction)skipButton:(UIButton *)sender;
-(IBAction)likeCommentButton:(UIButton *)sender;
@end
答案 0 :(得分:1)
要编写iOS应用,了解memory management rules。
至关重要在ViewControllerB,viewDidLoad中,您可以分配pvc。 再往下,您可以将pvc的视图添加为滚动条的子视图。这保留了pvc的观点,但不是pvc本身。然后当你释放pvc时,它的保留计数为零,当你稍后引用它时,它就消失了。崩溃。看起来你需要传入并保留对使用它的控制器中的pvc的引用。
答案 1 :(得分:0)
我不确定您使用PhotoViewController
(子类UIViewController
)而不是PhotoView
(子类UIView
)的原因。因为你没有使用viewcontroller的任何功能(没有生命周期方法和其他)。
如果您使用PhotoViewController
继承UIView
并删除了viewcontroller的方法,它将起作用,并且不会导致任何内存问题,因为您已经在与 Rayfleck 的讨论中讨论过这个问题。 (它将由父视图控制器保留。)
如果您正在考虑事件,那么这些事件也将由视图本身处理。但是如果你想在你的控制器中处理它,那么你可以轻松委托,或传递你的控制器参考并在其上调用事件。
谢谢,