iOS 復制一個UIView對象實現方法 – iPhone手機開發 iPhone軟體開發教學課程

iOS 復制一個UIView對象,項目中要做一個新手引導,也就是給某個頁面加個遮罩,然後突出顯示出一塊視圖,在寫點提示啥的。

我的思路是加一個一模一樣的視圖到遮罩上,但是問題來瞭,簡單的視圖是可以這麼搞,復雜一點的難道也要創建一個一模一樣的嗎,那樣豈不是太麻煩瞭。

能不能直接復制一份出來,然後加到遮罩上呢?

我們都知道復制數組、字典、字符串這些用copy,mutableCopy,然後我就想當然的用我的自定義View調瞭一下copy,結果很尷尬,直接給崩瞭,說是要實現copyWithZone這個方法。

總不能所有的自定義View都是實現一遍一個方法吧!

網友們給出這麼一個方法,我欣喜若狂,趕緊拿去試一試

NSData *archiveData = [NSKeyedArchiver archivedDataWithRootObject:view];  
UIView *copyView = [NSKeyedUnarchiver unarchiveObjectWithData:archiveData];

然而這個方法並不完美,在復制的copyView中,雖然所有的子控件都能顯示出來,但是地址都是nii,當然這不是問題的關鍵,最致命的是子控件裡面包含圓角的話,復制出來後,子控件的圓角都麼得啦。這就不能忍瞭,於是就有瞭這篇博客,我想瞭笨方法,給復制出來的View的子控件,加上本該有的圓角!

一言不合就上代碼:

@implementation GuideView

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.3];
        self.frame = [UIScreen mainScreen].bounds;
        self.alpha = 0;
    }
    return self;
}

+ (instancetype)guideView{
    return [[GuideView alloc] init];
}

- (void)addToView:(UIView *)view{
    [self addToView:view containCorner:NO];
}

/**  加給某個View上*/
- (void)addToView:(UIView *)view containCorner:(BOOL)containCorner{
    // 這樣復制後,如果有子控件設置瞭圓角,復制後圓角會失效,而且所有子控件雖然都能顯示正確,但地址都是nil
    NSData *archiveData = [NSKeyedArchiver archivedDataWithRootObject:view];
    UIView *copyView = [NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
    
    // 子控件如果包含圓角
    if (containCorner == YES) {
        
        // 替換子控件
        NSData * subData = [NSKeyedArchiver archivedDataWithRootObject:view.subviews];
        NSArray* subViews = [NSKeyedUnarchiver unarchiveObjectWithData:subData];
        [copyView removeAllSubviews];
        for (UIView *subview in subViews) {
            [copyView addSubview:subview];
        }
        
        // 在原View中找到設置瞭圓角的子控件
        for (UIView *subView in view.subviews) {
            
            if (subView.layer.cornerRadius != 0)
            {
                // 在復制好的View的子控件中遍歷,找到與之對應的子控件
                for (UIView *copySubView in copyView.subviews) {
                    
                    // 給找到的控件設置上圓角,這裡通過frame確定是否是同一個控件
                    if ([NSStringFromCGRect(copySubView.frame) isEqualToString:NSStringFromCGRect(subView.frame)]) {
                        copySubView.layer.cornerRadius = subView.layer.cornerRadius;
                        copySubView.layer.masksToBounds = YES;
                        break;
                    }
                }
            }
        }
    }
    copyView.frame = [view convertRect:view.bounds toView:kAppDelegate.window];
    [self addSubview:copyView];
}

- (void)show{
    [kAppDelegate.window addSubview:self];
    [UIView animateWithDuration:0.3 animations:^{
        self.alpha = 1;
    }];
}

- (void)disMiss{
    [UIView animateWithDuration:0.3 animations:^{
        self.alpha = 1;
    } completion:^(BOOL finished) {
          [self removeFromSuperview];
    }];
}

//- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//    [super touchesBegan:touches withEvent:event];
//    [self disMiss];
//}
@end

效果圖

:

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *