UIPageControl не работает с UIImageView в IOS7

В моих усилиях по обновлению моего приложения для поддержки IOS7 я узнал, что UIPageControl не поддерживает UIImageView. Они изменили его.

Я подклассифицирую UIPageControl, чтобы добавить обычные круги вместо обычных (приложенный пример)

Мой класс:

- (id)initWithFrame:(CGRect)frame 
{
    // if the super init was successfull the overide begins.
    if ((self = [super initWithFrame:frame])) 
    { 
        // allocate two bakground images, one as the active page and the other as the inactive
        activeImage = [UIImage imageNamed:@"active_page_image.png"];
        inactiveImage = [UIImage imageNamed:@"inactive_page_image.png"];
    }
    return self;
}

// Update the background images to be placed at the right position
-(void) updateDots
{
    for (int i = 0; i < [self.subviews count]; i++)
    {
        UIImageView* dot = [self.subviews objectAtIndex:i];
        if (i == self.currentPage) dot.image = activeImage;
        else dot.image = inactiveImage;
    }
}

// overide the setCurrentPage
-(void) setCurrentPage:(NSInteger)page
{
    [super setCurrentPage:page];
    [self updateDots];
}

PageControl (the blue is the current page)

Теперь в IOS7 я получил следующую ошибку:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setImage:]: unrecognized selector sent to instance 0xe02ef00'

и после исследования я понял, что следующий код вызывает ошибку:

UIImageView* dot = [self.subviews objectAtIndex:i];
if (i == self.currentPage) dot.image = activeImage;
    else dot.image = inactiveImage;

Я проверил subviews и увидел, что UIView вместо UIImageView. вероятно, Apple что-то изменила.

Есть идея, как это исправить?

Ответ 1

Похоже, что они изменили subviews на стандартные UIView s. Мне удалось обойти это, сделав это:

for (int i = 0; i < [self.subviews count]; i++)
{
    UIView* dotView = [self.subviews objectAtIndex:i];
    UIImageView* dot = nil;

    for (UIView* subview in dotView.subviews)
    {
        if ([subview isKindOfClass:[UIImageView class]])
        {
            dot = (UIImageView*)subview;
            break;
        }
    }

    if (dot == nil)
    {
        dot = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, dotView.frame.size.width, dotView.frame.size.height)];
        [dotView addSubview:dot];
    }

    if (i == self.currentPage)
    {
        if(self.activeImage)
            dot.image = activeImage;
    }
    else
    {
         if (self.inactiveImage)
             dot.image = inactiveImage;
    }
}

Ответ 2

Возможно, точка не является видом UIImageView, поэтому попробуйте вот это

UIImageView* dot = [self.subviews objectAtIndex:i];
if ([dot isKindOfClass:[UIImageView class]]) {
    if (i == self.currentPage) 
        dot.image = activeImage;
    else 
        dot.image = inactiveImage;
}

Ответ 3

У меня есть немного более чистое решение:

for (int i = 0; i < [self.subviews count]; i++) {
    UIView *dotView = [self.subviews objectAtIndex:i];
    if ([dotView isKindOfClass:[UIImageView class]]) {
        UIImageView* dot = (UIImageView*)dotView;
        dot.frame = CGRectMake(dot.frame.origin.x, dot.frame.origin.y, _activeImage.size.width, _activeImage.size.height);
        if (i == self.currentPage)
            dot.image = _activeImage;
        else
            dot.image = _inactiveImage;
    }
    else {
        dotView.frame = CGRectMake(dotView.frame.origin.x, dotView.frame.origin.y, _activeImage.size.width, _activeImage.size.height);
        if (i == self.currentPage)
            [dotView setBackgroundColor:[UIColor colorWithPatternImage:_activeImage]];
        else
            [dotView setBackgroundColor:[UIColor colorWithPatternImage:_inactiveImage]];
    }
}

Идея вместо добавления subview в UIView для iOS7 просто устанавливает фоновое изображение UIView.

Ответ 4

Просто немного рефакторинга для решения devgeek, чтобы сделать его немного более компактным

for (int i = 0; i < [self.subviews count]; i++) {
    UIImage *customDotImage = (i == self.currentPage) ? _activeDot : _inactiveDot;
    UIView *dotView = [self.subviews objectAtIndex:i];
    dotView.frame = CGRectMake(dotView.frame.origin.x, dotView.frame.origin.y, customDotImage.size.width, customDotImage.size.height);
    if ([dotView isKindOfClass:[UIImageView class]]) { // in iOS 6, UIPageControl contains UIImageViews
        ((UIImageView *)dotView).image = customDotImage;
    }
    else { // in iOS 7, UIPageControl contains normal UIViews
        dotView.backgroundColor = [UIColor colorWithPatternImage:customDotImage];
    }
}

Ответ 5

Просто переопределите layoutSubviews в вашем подклассе UIPageControl

- (void) layoutSubviews
{
    [super layoutSubviews];
    for (UIView* dot in self.subviews)
    {
        CGRect f = dot.frame;
        //sets all the dots to be 5x5
        f.size = CGSizeMake(5, 5);
        //need to reposition vertically as the dots get repositioned when selected
        f.origin.y = CGRectGetMidY(self.bounds) - CGRectGetHeight(f)/2;
        dot.frame = f;
        //update the cornerRadius to be sure that they are perfect circles
        dot.layer.cornerRadius = CGRectGetWidth(f)/2;
    }
}