热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Swift安全区域布局指南和可视格式语言

如何解决《Swift安全区域布局指南和可视格式语言》经验,为你挑选了3个好方法。

我想使用Apples可视化格式语言将视图约束到iOS 11中的新安全区域布局指南.但是,我得到一个例外:

- [NSLayoutYAxisAnchor nsli_superitem]:无法识别的选择器发送到实例0x1c447ed40

    //Make View Dictionary
    var views: [String: Any] = ["left": self.leftContainer]

    //Check swift version and add appropriate piece to the view dictionary
    if #available(iOS 11, *) {
        views["topGuide"] = self.view.safeAreaLayoutGuide.topAnchor
    }else{
        views["topGuide"] = self.topLayoutGuide
    }

    //Make the constraint using visual format language
    let leftVertical = NSLayoutConstraint.constraints(withVisualFormat: "V:[topGuide][left]|", options: [], metrics: nil, views: views)

    //Add the new constraint
    self.view.addConstraints(vertical)

我喜欢可视化格式语言的原因是因为在某些情况下你可以用更少的代码添加很多约束.

有任何想法吗?



1> matt..:

我想使用Apples可视化格式语言将视图约束到新的"安全区域布局指南"

你不能.通过可视格式语言无法访问安全区域布局指南.我已经提交了一个错误,我建议你这样做.



2> aleh..:

我们在这里扩展了视觉格式化语言,所以现在你可以反对"<|" 当你的意思是safeAreaLayoutGuide.我希望Apple能做到这样的事情.

例如,如果您有以下iOS 11之前的代码:

[NSLayoutConstraint activateConstraints:[NSLayoutConstraint
     constraintsWithVisualFormat:@"V:[_button]-(normalPadding)-|"
    options:0 metrics:metrics views:views
]];

现在,您要确保按钮位于iPhone X上的安全底部边距上方,然后执行以下操作:

[NSLayoutConstraint activateConstraints:[NSLayoutConstraint
    mmm_constraintsWithVisualFormat:@"V:[_button]-(normalPadding)-<|"
    options:0 metrics:metrics views:views
]];

而已.它会在iOS 9和10上将按钮锚定到其超级视图的底部,但是将其锚定到iOS 11上的safeAreaLayoutGuide的底部.

请注意,使用"|>"固定到顶部不会排除iOS 9和10上的状态栏.

// In @interface/@implementation NSLayoutConstraint (MMMUtil)
// ...

+(NSArray *)mmm_constraintsWithVisualFormat:(NSString *)format
    options:(NSLayoutFormatOptions)opts
    metrics:(NSDictionary *)metrics
    views:(NSDictionary *)views
{
    if ([format rangeOfString:@"<|"].location == NSNotFound && [format rangeOfString:@"|>"].location == NSNotFound ) {
        // No traces of our special symbol, so do nothing special.
        return [self constraintsWithVisualFormat:format options:opts metrics:metrics views:views];
    }

    if (![UIView instancesRespondToSelector:@selector(safeAreaLayoutGuide)]) {
        // Before iOS 11 simply use the edges of the corresponding superview.
        NSString *actualFormat = [format stringByReplacingOccurrencesOfString:@"<|" withString:@"|"];
        actualFormat = [actualFormat stringByReplacingOccurrencesOfString:@"|>" withString:@"|"];
        return [NSLayoutConstraint constraintsWithVisualFormat:actualFormat options:opts metrics:metrics views:views];
    }

    //
    // OK, iOS 11+ time.
    // For simplicity we replace our special symbols with a reference to a stub view, feed the updated format string
    // to the system, and then replace every reference to our stub view with a corresponding reference to safeAreaLayoutGuide.
    //

    UIView *stub = [[UIView alloc] init];
    static NSString * const stubKey = @"__MMMLayoutStub";
    NSString *stubKeyRef = [NSString stringWithFormat:@"[%@]", stubKey];
    NSDictionary *extendedViews = [@{ stubKey : stub } mmm_extendedWithDictionary:views];

    NSString *actualFormat = [format stringByReplacingOccurrencesOfString:@"<|" withString:stubKeyRef];
    actualFormat = [actualFormat stringByReplacingOccurrencesOfString:@"|>" withString:stubKeyRef];

    NSArray *cOnstraints= [NSLayoutConstraint constraintsWithVisualFormat:actualFormat options:opts metrics:metrics views:extendedViews];

    NSMutableArray *processedCOnstraints= [[NSMutableArray alloc] init];
    for (NSLayoutConstraint *c in constraints) {
        UIView *firstView = c.firstItem;
        UIView *secOndView= c.secondItem;
        NSLayoutConstraint *processed;
        if (firstView == stub) {
            if (![secondView isKindOfClass:[UIView class]]) {
                NSAssert(NO, @"We only support UIView with <| and |> anchors, got %@", secondView.class);
                continue;
            }
            processed = [self
                constraintWithItem:secondView.superview.safeAreaLayoutGuide attribute:_MMMOppositeAttribute(c.firstAttribute)
                relatedBy:c.relation
                toItem:secondView attribute:c.secondAttribute
                multiplier:c.multiplier constant:c.constant
                priority:c.priority
                identifier:@"MMMSafeAreaFirstItemConstraint"
            ];
        } else if (secOndView== stub && [firstView isKindOfClass:[UIView class]]) {
            if (![firstView isKindOfClass:[UIView class]]) {
                NSAssert(NO, @"We only support UIView with <| and |> anchors, got %@", secondView.class);
                continue;
            }
            processed = [self
                constraintWithItem:firstView attribute:c.firstAttribute
                relatedBy:c.relation
                toItem:firstView.superview.safeAreaLayoutGuide attribute:_MMMOppositeAttribute(c.secondAttribute)
                multiplier:c.multiplier constant:c.constant
                priority:c.priority
                identifier:@"MMMSafeAreaSecondItemConstraint"
            ];
        } else {
            processed = c;
        }
        [processedConstraints addObject:processed];
    }

    return processedConstraints;
}

+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1
    relatedBy:(NSLayoutRelation)relation
    toItem:(id)view2 attribute:(NSLayoutAttribute)attr2
    multiplier:(CGFloat)multiplier constant:(CGFloat)c
    priority:(UILayoutPriority)priority
    identifier:(NSString *)identifier
{
    NSLayoutConstraint *result = [NSLayoutConstraint constraintWithItem:view1 attribute:attr1 relatedBy:relation toItem:view2 attribute:attr2 multiplier:multiplier constant:c];
    result.priority = priority;
    result.identifier = identifier;
    return result;
}

// @end

static inline NSLayoutAttribute _MMMOppositeAttribute(NSLayoutAttribute a) {
    switch (a) {
        // TODO: support trailing/leading in the same way
        case NSLayoutAttributeLeft:
            return NSLayoutAttributeRight;
        case NSLayoutAttributeRight:
            return NSLayoutAttributeLeft;
        case NSLayoutAttributeTop:
            return NSLayoutAttributeBottom;
        case NSLayoutAttributeBottom:
            return NSLayoutAttributeTop;
        // These two are special cases, we see them when align all X or Y flags are used.
        case NSLayoutAttributeCenterY:
            return NSLayoutAttributeCenterY;
        case NSLayoutAttributeCenterX:
            return NSLayoutAttributeCenterX;
        // Nothing more.
        default:
            NSCAssert(NO, @"We don't expect other attributes here");
            return a;
    }
}

@interface NSDictionary (MMMUtil)
- (NSDictionary *)mmm_extendedWithDictionary:(NSDictionary *)d;    
@end

@implementation NSDictionary (MMMUtil)

- (NSDictionary *)mmm_extendedWithDictionary:(NSDictionary *)d {

    if (!d || [d count] == 0)
        return self;

    NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithDictionary:self];
    [result addEntriesFromDictionary:d];
    return result;
}

@end



3> Moebius..:

我知道这不是VFL,但是有一个叫做的工厂类NSLayoutAnchor可以让创建约束变得更加干净和简洁.

例如,我能够使用一条紧凑的线将UILabel的顶部锚点固定到安全区域的顶部锚点:

label.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true

请注意,safeAreaLayoutGuide需要iOS 11.对于旧版本,请替换self.view.safeAreaLayoutGuide.topAnchorself.topLayoutGuide.bottomAnchor.

再说一次,我知道这不是VFL,但这似乎是我们现在所拥有的.


推荐阅读
  • GDB 使用心得与技巧总结
    在使用 GDB 进行调试时,可以采用以下技巧提升效率:1. 通过设置 `set print pretty on` 来美化打印输出,使数据结构更加易读;2. 掌握常见数据结构的打印方法,如链表、树等;3. 利用 `info locals` 命令查看当前作用域内的所有局部变量;4. 在需要进行类型强制转换时,正确使用语法,例如 `p (Test::A *) pObj`。这些技巧能够显著提高调试的便捷性和准确性。 ... [详细]
  • Squaretest:自动生成功能测试代码的高效插件
    本文将介绍一款名为Squaretest的高效插件,该工具能够自动生成功能测试代码。使用这款插件的主要原因是公司近期加强了代码质量的管控,对各项目进行了严格的单元测试评估。Squaretest不仅提高了测试代码的生成效率,还显著提升了代码的质量和可靠性。 ... [详细]
  • 开发笔记:深入解析Android自定义控件——Button的72种变形技巧
    开发笔记:深入解析Android自定义控件——Button的72种变形技巧 ... [详细]
  • 在探讨C语言编程文本编辑器的最佳选择与专业推荐时,本文将引导读者构建一个基础的文本编辑器程序。该程序不仅能够打开并显示文本文件的内容及其路径,还集成了菜单和工具栏功能,为用户提供更加便捷的操作体验。通过本案例的学习,读者可以深入了解文本编辑器的核心实现机制。 ... [详细]
  • 本文介绍如何在 Android 中自定义加载对话框 CustomProgressDialog,包括自定义 View 类和 XML 布局文件的详细步骤。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 当使用 `new` 表达式(即通过 `new` 动态创建对象)时,会发生两件事:首先,内存被分配用于存储新对象;其次,该对象的构造函数被调用以初始化对象。为了确保资源管理的一致性和避免内存泄漏,建议在使用 `new` 和 `delete` 时保持形式一致。例如,如果使用 `new[]` 分配数组,则应使用 `delete[]` 来释放内存;同样,如果使用 `new` 分配单个对象,则应使用 `delete` 来释放内存。这种一致性有助于防止常见的编程错误,提高代码的健壮性和可维护性。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 在Java项目中,当两个文件进行互相调用时出现了函数错误。具体问题出现在 `MainFrame.java` 文件中,该文件位于 `cn.javass.bookmgr` 包下,并且导入了 `java.awt.BorderLayout` 和 `java.awt.Event` 等相关类。为了确保项目的正常运行,请求提供专业的解决方案,以解决函数调用中的错误。建议从类路径、依赖关系和方法签名等方面入手,进行全面排查和调试。 ... [详细]
  • 深入解析 Android 中 EditText 的 getLayoutParams 方法及其代码应用实例 ... [详细]
  • ButterKnife 是一款用于 Android 开发的注解库,主要用于简化视图和事件绑定。本文详细介绍了 ButterKnife 的基础用法,包括如何通过注解实现字段和方法的绑定,以及在实际项目中的应用示例。此外,文章还提到了截至 2016 年 4 月 29 日,ButterKnife 的最新版本为 8.0.1,为开发者提供了最新的功能和性能优化。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • 设计实战 | 10个Kotlin项目深度解析:首页模块开发详解
    设计实战 | 10个Kotlin项目深度解析:首页模块开发详解 ... [详细]
  • 如何使用和示例代码解析 org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom.getPropertyChain() 方法 ... [详细]
author-avatar
Ycandy
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有