Storyboard/Xib 进阶教程

4 篇文章 0 订阅
3 篇文章 0 订阅

引言:

2007年第一部iPhone问世后,智能手机开始了取代PC终端的脚步。

时间来到2016年。

在时代巨浪的推动下,如今,移动互联网已然成为了IT领域的主战场。今天的iOS应用程序已经再不是从前那简单、娇小的弱女子了。手机淘宝、网易海购等原生和Html5结合的超级App层出不穷。Hybrid模式大红大紫,却也先天不足。

在iOS开发领域,我一直钟爱IB。

IB的源代码由Xml所书写,生涩难读,难以驾驭。

所以,IB开发几乎都是在图形化界面中进行的。

但这却并未妨碍IB成为iOS开发中最具效率的开发方式。

至于个中原因,还是Xcode强大的GUI操作界面和IB灵活的 Runtime注入,AutoLayout简洁的适配设置,SizeClass的iPhone/iPad兼容设置。

有时我在想,如果将IB的源代码进化成Html5风格书写会有什么样的一番风景呢。

在我眼中,以IB书写界面为主流的iOS开发模式,是最有可能进化成为完美的Hybrid模式,试想一下,兼容H5的IB配合Xcode强大的IDE编辑器,会带来一种何等愉悦的开发体验,会产生一种何等优异的Hybrid模式。性能优异,界面动态,有序的将逻辑放在前端和后端。这才是我心目中的Hybrid—既可以轻松的随App一起打包,还拥有卓越的性能,又可以随时对界面进行动态替换。

从iOS App 支持通过Tag标记来延迟下载IB文件可以得出 ,这在技术实现上不会有任何问题。

可是一心要控制App的性能和质量的Apple会大开绿灯吗?

短期内应该不会,但动态界面,固定逻辑也许会成为可能。

好了,说了这么多,我们也应该开始今天的主题了。

第一章:常见崩溃排查

连awakeFromeNib都没有执行,程序却崩溃了

连viewDidLoad都没有执行,程序还是崩溃了

这个 控件/界面 才刚一使用,程序就已经崩溃了

只是改变一点看起来没有任何问题的layout,程序崩溃了

合并代码后我的IB文件突然打不开了

没有任何报错,没有任何警告,程序崩溃了,IB,IB,真真是让人又爱又恨


相信许多入行iOS开发不久,或者使用IB不久的朋友都有遇到过这样的问题。这也是很多朋友放弃在实际项目中使用IB的原因之一。

IB仿佛是一把双刃剑,极大的提升开发效率,有着优异视图解耦性,却也伴随着难缠的故障排查。

如果就到此而止了,您还会继续使用IB吗?


我想绝大部分开发者会放弃它,或者只使用Xib而放弃Storyboard,尤其是站在生产第一线的朋友们。

在实际开发中我也常常遇到这样的朋友,因为这样或者那样的原因而弃用了IB,或者仅仅用IB搭建了View,却用代码给它设置一切。

在我们实际开发中,如果不使用IB,或者不部分使用Storyboard,在开发效率上,明显会慢于有着AndroidStudio加成的Android player。

这让一向自称程序高富帅的我们情何以堪。


好了,言归正转。


常见崩溃点:


1、Terminating app due to uncaught exception ‘NSUnknownKeyException'

-IB控件关联代码错误


问题描述:


控件关联对象或者事件(拉线到代码)后,移除了代码中的(对象或者方法)却没有移除控件上的引用(Referencing)。此种情况必崩。


解决方案:


如果同一IB文件控件较少:


方案,展开IB右边工具栏,切换到 Connection Inspector(带箭头那个)。切换点击控件逐一排查 Referencing,先检查同一控件有无重复Referencing(通常情况下是更改了代码中的关联对象,而IB中没有移除原有的Referencing导致),如果有重复Referencing再检查哪一个是真正对应代码的Referencing。如果没有找到问题,再检查是否所有的关联在代码中都有对应的存在(包括事件 和方法)。



2、reason: [<UI*** 0x15550640> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key

-IB keyPath 设置错误(如果没用过keyPath参考 http://blog.csdn.net/bsn1928/article/details/51372197


问题描述:


控件设置了不存在的keyPath。或者不应该设置KeyPath的控件被设置了KeyPath。

此种情况必崩。


解决方案:


如果同一IB文件控件较少,使用方案1,反之使用方案2:


方案1,展开IB右边工具栏,切换到 Identity Inspector(方框带文档图标那个)。展开User Defiend Runtime Attributes,找到错误提示中这段代码 [<UI*** 0x15550640> setValue:forUndefinedKey:] 的键,按类名逐一检查Key Path是否为空,然后修复之。


方案2,右键 IB 文件 Open As -> Source Code。Command + F搜索  KeyPath=“” 。如果未找到,找到错误提示中这段代码 [<UI*** 0x15550640> setValue:forUndefinedKey:] 的键,按类名搜索之,逐一排查,是否设置了无法找到的KeyPath。找到后,移除此KeyPath即可修复(注:源代码中要按键值对删除,否则将无法编译通过,至于为什么,玩过Html的都应该知道)。(当然你也可以写个脚本来完成如此复杂的操作,这里只阐述原理)



第二章:利用IBDesignable创建自定义IB控件

1、准备:Xcode 7.* +

这里介绍一下Label控件的自定义,其它控件以此类推。

新建Swift工程IBExtension,新建 IBLabel 继承自 UILabel。在类开始前加入

@IBDesignable

代码如下


//  在OC中 IB_Designable

//  在OC中 IBInspectable


import UIKit


@IBDesignable

class IBLabel: UILabel {

    @IBInspectable var cornerRadius:CGFloat = 0{

        didSet{

            layer.cornerRadius = cornerRadius

            layer.masksToBounds = cornerRadius > 0

        }

    }

    @IBInspectable var borderWidth:CGFloat = 0{

        didSet{

            layer.masksToBounds = cornerRadius > 0

            layer.borderWidth = borderWidth

        }

    }

    @IBInspectable var borderColor:UIColor?{

        didSet{

            layer.masksToBounds = borderColor != nil

            layer.borderColor = borderColor?.CGColor

        }

    }

    @IBInspectable var allowSelected:Bool = false{

        didSet{

            if  allowSelected{

                userInteractionEnabled = true

                addGestureRecognizer(tap)

            }

            else{

                isSelected = false

                userInteractionEnabled = false

                removeGestureRecognizer(tap)

            }

        }

    }

    @IBInspectable var hiddenBorderWhenSelected = false{

        didSet{

            if hiddenBorderWhenSelected {layer.borderWidth = 0}

            else {layer.borderWidth = borderWidth}

        }

    }

    @IBInspectable var isSelected:Bool = false{

        didSet{

            if !allowSelected{

                backgroundColor = normalBackgroundColor

                textColor = normalTextColor

                return

            }

            if isSelected{

                backgroundColor = selectedBackgroundColor

                textColor = selectedTextColor

                if hiddenBorderWhenSelected {layer.borderWidth = 0}

            }

            else{

                backgroundColor = normalBackgroundColor

                textColor = normalTextColor

                if hiddenBorderWhenSelected {layer.borderWidth = borderWidth}

            }

        }

    }

    @IBInspectable var normalTextColor:UIColor?

    @IBInspectable var selectedTextColor:UIColor?

    @IBInspectable var normalBackgroundColor:UIColor?

    @IBInspectable var selectedBackgroundColor:UIColor?

    lazy var tap:UITapGestureRecognizer = {

        let tapGesture = UITapGestureRecognizer()

        tapGesture .addTarget(self, action: #selector(IBLabel.didSelected(_:)))

        return tapGesture

    }()

    func didSelected(gesture:UITapGestureRecognizer) {

        isSelected = !isSelected

    }

}


打开IB新建Label 展开IB右边工具栏,切换到 Identity Inspector 在 Class 类中输入我们刚才创建的IBLabel

然后切换到 Attributes Inspector 这时你可以看到你的自定义属性

如果你成功了

你会感受到IB突然变得如此的强大

如果失败了

不要着急,点击 Editor->Automaticaly Referesh View

然后再切换回来

如果还不行

没关系,重启Xcode



第三章:使用Storyboard创建静态列表,并配置动态刷新方法(下期再讲解)






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值