加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

objective-c – 在保留自动布局约束的同时更换NSView

发布时间:2020-12-16 05:55:53 所属栏目:百科 来源:网络整理
导读:我想在保留约束的同时将一个NSView替换为其他视图. 我有一个superview,subview,因为它是小孩和占位符,我打算迁移到子视图的地方. 但它似乎是代码 [[superview] replaceSubview:subview with:placeholder]; 删除与子视图相关的所有约束,并删除子视图. 约束如
我想在保留约束的同时将一个NSView替换为其他视图.

我有一个superview,subview,因为它是小孩和占位符,我打算迁移到子视图的地方.
但它似乎是代码

[[superview] replaceSubview:subview with:placeholder];

删除与子视图相关的所有约束,并删除子视图.

约束如何从一个视图“复制”到另一个视图?

解决方法

这是我写的很久以前的一些代码来做你所要求的.

我的代码用于在同一个超级视图中交换两个NSView,但是您可以轻松地将其替换为剥离不必要的位,并以仔细的顺序执行视图/约束添加和删除.事实上,我在“代理”视图控制器类中有一个较短的版本的代码,它完全符合你的要求,但我不能共享,因为它是一个不属于我的专有项目.

我会告诉你,你需要做的是将约束从代理视图复制到新视图,然后将新视图添加到超级视图.之后,将代理的超级视图约束复制到新视图,只有在您执行此操作后,才能从超级视图中删除代理视图.

- (void)swapView:(NSView*) source withView:(NSView*) dest persist:(BOOL) persist
{
    NSLog(@"swapping %@ with %@",source.identifier,dest.identifier);
    // !!!: adjust the "Auto Layout" constraints for the superview.
    // otherwise changing the frames is impossible. (instant reversion)
    // we could disable "Auto Layout",but let's try for compatibility

    // TODO: we need to either enforce that the 2 controls have the same superview
    // before accepting the drag operation
    // or modify this code to take two diffrent superviews into account

    // we are altering the constraints so iterate a copy!
    NSArray* constraints = [dest.superview.constraints copy];
    for (NSLayoutConstraint* constraint in constraints) {
        id first = constraint.firstItem;
        id second = constraint.secondItem;
        id newFirst = first;
        id newSecond = second;

        BOOL match = NO;
        if (first == dest) {
            newFirst = source;
            match = YES;
        }
        if (second == dest) {
            newSecond = source;
            match = YES;
        }
        if (first == source) {
            newFirst = dest;
            match = YES;
        }
        if (second == source) {
            newSecond = dest;
            match = YES;
        }
        if (match && newFirst) {
            [dest.superview removeConstraint:constraint];
            @try {
                NSLayoutConstraint* newConstraint = nil;
                newConstraint = [NSLayoutConstraint constraintWithItem:newFirst
                                                             attribute:constraint.firstAttribute
                                                             relatedBy:constraint.relation
                                                                toItem:newSecond
                                                             attribute:constraint.secondAttribute
                                                            multiplier:constraint.multiplier
                                                              constant:constraint.constant];
                newConstraint.shouldBeArchived = constraint.shouldBeArchived;
                newConstraint.priority = NSLayoutPriorityWindowSizeStayPut;
                [dest.superview addConstraint:newConstraint];
            }
            @catch (NSException *exception) {
                NSLog(@"Constraint exception: %@nFor constraint: %@",exception,constraint);
            }
        }
    }
    [constraints release];

    NSMutableArray* newSourceConstraints = [NSMutableArray array];
    NSMutableArray* newDestConstraints = [NSMutableArray array];

    // again we need a copy since we will be altering the original
    constraints = [source.constraints copy];
    for (NSLayoutConstraint* constraint in constraints) {
        // WARNING: do not tamper with intrinsic layout constraints
        if ([constraint class] == [NSLayoutConstraint class]
            && constraint.firstItem == source) {
            // this is a source constraint. we need to copy it to the destination.
            NSLayoutConstraint* newConstraint = nil;
            newConstraint = [NSLayoutConstraint constraintWithItem:dest
                                                         attribute:constraint.firstAttribute
                                                         relatedBy:constraint.relation
                                                            toItem:constraint.secondItem
                                                         attribute:constraint.secondAttribute
                                                        multiplier:constraint.multiplier
                                                          constant:constraint.constant];
            newConstraint.shouldBeArchived = constraint.shouldBeArchived;
            [newDestConstraints addObject:newConstraint];
            [source removeConstraint:constraint];
        }
    }
    [constraints release];

    // again we need a copy since we will be altering the original
    constraints = [dest.constraints copy];
    for (NSLayoutConstraint* constraint in constraints) {
        // WARNING: do not tamper with intrinsic layout constraints
        if ([constraint class] == [NSLayoutConstraint class]
            && constraint.firstItem == dest) {
            // this is a destination constraint. we need to copy it to the source.
            NSLayoutConstraint* newConstraint = nil;
            newConstraint = [NSLayoutConstraint constraintWithItem:source
                                                         attribute:constraint.firstAttribute
                                                         relatedBy:constraint.relation
                                                            toItem:constraint.secondItem
                                                         attribute:constraint.secondAttribute
                                                        multiplier:constraint.multiplier
                                                          constant:constraint.constant];
            newConstraint.shouldBeArchived = constraint.shouldBeArchived;
            [newSourceConstraints addObject:newConstraint];
            [dest removeConstraint:constraint];
        }
    }
    [constraints release];

    [dest addConstraints:newDestConstraints];
    [source addConstraints:newSourceConstraints];

    // auto layout makes setting the frame unnecissary,but
    // we do it because its possible that a module is not using auto layout
    NSRect srcRect = source.frame;
    NSRect dstRect = dest.frame;
    // round the coordinates!!!
    // otherwise we will have problems with persistant values
    srcRect.origin.x = round(srcRect.origin.x);
    srcRect.origin.y = round(srcRect.origin.y);
    dstRect.origin.x = round(dstRect.origin.x);
    dstRect.origin.y = round(dstRect.origin.y);

    source.frame = dstRect;
    dest.frame = srcRect;

    if (persist) {
        NSString* rectString = NSStringFromRect(srcRect);
        [[_theme prefrences] setObject:rectString forKey:dest.identifier];
        rectString = NSStringFromRect(dstRect);
        [[_theme prefrences] setObject:rectString forKey:source.identifier];
    }
}

你可以放心地忽略你想象的情况下的持久性.在我的情况下,我想实现iOS跳板功能(能够点按并按住一个按钮,它会跳动,让我拖动到另一个按钮,并在发射之间交换位置)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读