热门标签 | 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,但这似乎是我们现在所拥有的.


推荐阅读
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 本文介绍了Python语言程序设计中文件和数据格式化的操作,包括使用np.savetext保存文本文件,对文本文件和二进制文件进行统一的操作步骤,以及使用Numpy模块进行数据可视化编程的指南。同时还提供了一些关于Python的测试题。 ... [详细]
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社区 版权所有