Я работаю над приложением, которое использует UIScrollView для прокрутки множества слайдов. Когда приложение открывается, оно создает слайды и передает их в представление с прокруткой. Мое приложение также имеет таймер, который заставляет UIScrollView прокручивать слайды.
У меня также есть кнопка настроек. Когда я нажимаю на эту кнопку, она открывает панель настроек. Таймер недействителен и установлен на nil
. Когда откроется панель настроек, пользователь может изменить такие вещи, как тема приложения, слайды и направление анимации.
Когда панель настроек закрыта, настройки применяются: слайды удаляются из UIScrollView, а UIScrollView получает новый NSArray слайдов для работы. Затем UIScrollView размещает новые слайды в правильном порядке и направлении. Таймер сброшен.
Один раз, примерно каждые 14-16 раз, происходит сбой приложения при запуске dismissAndRestart
(код "close"). Я не уверен почему. Я думал, что у меня утечка памяти, и, видимо, так и есть, но я не вижу, где.
Вот мой код:
Это запускается при запуске:
- (void)viewDidLoad {
[scrollView setPagingEnabled:YES];
}
- (void) viewWillAppear:(BOOL)animated{
[self prepareViews];
[self applyTheme];
}
- (void) viewDidAppear:(BOOL)animated{
[self createTimerWithInterval:kScrollInterval];
}
Метод рабочей лошадки, который загружает представления в скроллер. (Также удаляет старые):
- (void)loadViews:(NSArray *)views IntoScroller:(UIScrollView *)scroller withDirection:(NSString *)direction{
[scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[scrollView setShowsHorizontalScrollIndicator: NO];
[scrollView setShowsVerticalScrollIndicator:NO];
scrollView.scrollsToTop = NO;
if([direction isEqualToString:@"horizontal"]){
scrollView.frame = CGRectMake(0, 0, 1024, 768);
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [[NSNumber numberWithUnsignedInt:[views count]] floatValue], scrollView.frame.size.height);
}else if([direction isEqualToString:@"vertical"]){
scrollView.frame = CGRectMake(0, 0, 1024, 768);
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, scrollView.frame.size.height * [[NSNumber numberWithUnsignedInt:[views count]] floatValue]);
}
for (int i=0; i<[[NSNumber numberWithUnsignedInt:[views count]] intValue]; i++) {
[[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view] setFrame:scrollView.frame];
if([direction isEqualToString:@"horizontal"]){
[[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view] setFrame:CGRectMake(i * [[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view].frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height)];//CGRectMake(i * announcementView.view.frame.size.width, -scrollView.frame.origin.x, scrollView.frame.size.width, scrollView.frame.size.height)];
}else if([direction isEqualToString:@"vertical"]){
[[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view] setFrame:CGRectMake(0, i * [[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view].frame.size.height, scrollView.frame.size.width, scrollView.frame.size.height)];
}
[scrollView addSubview:[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view]];
}
}
Создание таймера для автоматической прокрутки:
#pragma mark -
#pragma mark Create the Timer to automate scrolling
- (void) createTimerWithInterval:(float)interval{
self.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(scrollWrapperForTimer) userInfo:nil repeats:YES];
}
Функция обертки для функции таймера. (Это было необходимо до того, как направление было NSUserDefault, теперь мне это не нужно.)
#pragma mark -
#pragma mark Scroll Automatically Every N seconds
- (void) scrollWrapperForTimer{
[self scrollToNewViewInDirection:kDirection];
}
- (void)scrollToNewViewInDirection:(NSString *)direction{
if([[NSUserDefaults standardUserDefaults] boolForKey:@"animated_scrolling"] == YES){
if([direction isEqualToString:@"horizontal"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(scrollView.contentOffset.x + scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}
}else if([direction isEqualToString:@"vertical"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(0, scrollView.contentOffset.y + scrollView.frame.size.height, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}
}
}else {
if([direction isEqualToString:@"horizontal"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(scrollView.contentOffset.x + scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}
}else if([direction isEqualToString:@"vertical"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(0, scrollView.contentOffset.y + scrollView.frame.size.height, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}
}
}
}
Этот метод вызывается при нажатии кнопки «Готово» на панели настроек.
#pragma mark -
#pragma mark Restart the program
- (void) dismissAndRestart{
[self prepareViews];
[self applyTheme];
[self dismissModalViewControllerAnimated:YES];
[self createTimerWithInterval:kScrollInterval];
}
Это создает правильные файлы изображений и загружает их на место:
#pragma mark -
#pragma mark Apply the theme to the main view
- (void) applyTheme{
//Front panel
UIImage *frontImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[[NSString stringWithFormat:@"%@_front", kTheme]description] ofType:@"png"]];
[self.overlayImage setImage:frontImage];
[frontImage release];
//Back Panel
if([kTheme isEqualToString:@"walnut"]){
[self.backgroundImage setHidden:NO];
UIImage *backImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[[NSString stringWithFormat:@"%@_back", kTheme]description] ofType:@"png"]];
[self.backgroundImage setImage:backImage];
[backImage release];
}else if([kTheme isEqualToString:@"metal"]){
[self.backgroundImage setHidden:YES];
[self.view setBackgroundColor: [UIColor scrollViewTexturedBackgroundColor]];
}
//Gabbai Button
UIImage *gabbaiImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[[NSString stringWithFormat:@"%@_settings_button", kTheme]description] ofType:@"png"]];
[self.gabbaiButton setImage:gabbaiImage forState:UIControlStateNormal];
[gabbaiImage release];
}
Еще одна функция-обертка, которую необходимо изменить:
#pragma mark -
#pragma mark Slide View related
- (void) prepareViews{
[self loadViews:[self createandReturnViews] IntoScroller:scrollView withDirection:kDirection];
}
Создает массив слайдов для передачи в скроллер:
//recreation of the views causes a delay each time the admin panel is closed.
- (NSArray*) createandReturnViews{
NSMutableArray *announcements = [NSMutableArray array];
NSArray *announcementsArray = [NSArray arrayWithObjects: @"Welcome to\nGabbai HD!",
@"First slide",
@"Second Slide",
@"Third Slide",
@"etc.",
nil];
for (int i = 0; i<[[NSNumber numberWithUnsignedInteger:[announcementsArray count]] intValue]; i++) {
MBAnnouncementViewController *announcement = [[MBAnnouncementViewController alloc] initWithNibName:@"MBAnnouncementViewController" bundle:nil];
[announcement setAnnouncementText:[announcementsArray objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntegerValue]]];
[announcements addObject:announcement];
[announcement release];
}
return announcements;
}
Почему на моей панели настроек происходит сбой приложения при закрытии?