前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《iOS UI 开发捷径 利用 Interface Builder 高效、优雅地开发 UI》 读书笔记第1章 Interface Bundle 概要第2章 使用 Interface Builder第3

《iOS UI 开发捷径 利用 Interface Builder 高效、优雅地开发 UI》 读书笔记第1章 Interface Bundle 概要第2章 使用 Interface Builder第3

作者头像
iOSDevLog
发布2018-05-17 11:14:39
2.5K0
发布2018-05-17 11:14:39
举报
文章被收录于专栏:iOSDevLog

第1章 Interface Bundle 概要


Bundle

一种标准化的层次结构,保存了可执行代码及代码所需要的资源。

nib

Next Interface Builder

Interface Builder 的优点

  1. 开发和维护效率高
  2. 减少大量的 UI 代码和“胶水代码”
  3. 适配变得十分简单
  4. IB 也可以做一些非 UI 的事情
  5. 利用 IB 学习控件可以达到事半功倍的效果

Interface Builder 的缺点

  1. IB 的执行效率没有纯代码高
  2. 使用 IB 开发的过程中容易出现一些小问题
  3. 有一定的学习成本
  4. 文件易冲突
  5. 没有代码表达清晰
  6. 不利于代码的封闭和工程架构的组织

Interface Builder 学习的特点

  1. 简单,容易入门
  2. 容易犯错误
  3. 有很多的“坑”,需要积累属于自己的经验

Interface Builder 的发展

xib -> sb -> AutoLayout -> LaunchScreen.storyboard

苹果越来越重视 IB。

CocoaPods

代码语言:javascript
复制
# 1 最新版本
pod 'AFNetworking'

# 2 最新的2.x版本
pod 'AFNetworking', '~>2.5.3'

# 3 指定版本
pod 'AFNetworking', '2.5.3' 

试用

代码语言:javascript
复制
$ pod try AFNetworking

Podfile文件与CocoaPods的三种依赖方式

  • 远程依赖
代码语言:javascript
复制
# master
pod 'Alamofile', :git => 'https://github.com/Alamofile/Alamofile.git'

# branch
pod 'Alamofile', :git => 'https://github.com/Alamofile/Alamofile.git', :branch -> 'dev'

# commit
pod 'Alamofile', :git => 'https://github.com/Alamofile/Alamofile.git', :commit => '0f506b1c45'
  • 本地依赖
代码语言:javascript
复制
pod 'AFNetworking', :path => '../externals/libs/AFNetworking'
  • 私有依赖
代码语言:javascript
复制
pod 'AFNetworking', :podspec => '../externals/libs/AFNetworking.podspec'

“:podspec=>”用于指定本地的一个xxx.podspec文件。

podspec文件

代码语言:javascript
复制
$ pod init
$ cat Podfile

第2章 使用 Interface Builder


解决冲突

  1. 解决普通IB文件冲突

Open As -> Source Code

代码语言:javascript
复制
<<<<<<<

=======

>>>>>>>

编辑好,再删除这三行就可以了。

  1. 解决 Xcode 8 引起的 IB 文件冲突

如果用 Source Code 不能打开,就用文件编辑器(vim, etc)打开,把systemVersion等冲突解决。

关联 xib 文件与源文件

  1. 关联 xib 文件与 UIView 子类的源文件
  • 新建一个空的xib文件,拖一个UIView上去
  • 新建一个继承自UIView的源文件
  • 选中xib文件里的View,把class改为上面

@IBOutlet 与 @IBAction

连线

设计模式之MVC

mvc

理解 File's Owner

关联 xib 文件与 UIViewController 子类的源文件

  • 自定义一个 VC 的 View 的两种方法
  1. 在 IB 文件中选中 VC 所在的 View,在 Show the Identity inspector 中设置 Class 标签的值为自定义的 View 的类名。
  2. 在源文件的 loadView() 方法里设置该 VC 的 View 属性为这个自定义的 View。
代码语言:javascript
复制
override func loadView() {
    self.view = CustomView.init(frame: UIScreen.main.bounds)
}
  • File's Owner 指向 VC
  • VC 的 View 连线

xib 既可以与 UIView 关联,也可以与 UIViewController 关联,也可以同时关联 UIView 与 UIViewController

使用 xib

  1. 通过 Bundle 方式加载
  2. 通过 UINib 方式加载

使用与UIView子类源文件关联的xib

Bundle
代码语言:javascript
复制
- (NSArray *)loadNibNamed:(NSString *)name 
                    owner:(id)owner 
                  options:(NSDictionary *)options;
代码语言:javascript
复制
func loadNibNamed(_ name: String, 
            owner: Any?, 
          options: [AnyHashable : Any]? = nil) -> [Any]?

Parameters 参数

  • name The name of the nib file, which need not include the .nib extension. nib名称
  • owner The object to assign as the nib’s File's Owner object. 如果xib文件有File's Owner,一定传其实例对象,否则传nil
  • options A dictionary containing the options to use when opening the nib file. For a list of available keys for this dictionary, see UIKit Nib Loading Options.
Bundle Demo
代码语言:javascript
复制
let testView = Bundle.main.loadNibNamed("TestView", owner: nil, options: nil)?[0] as! UIView
view.addSubview(testView)
UINib
代码语言:javascript
复制
NS_CLASS_AVAILABLE_IOS(4_0) @interface UINib : NSObject 

// If the bundle parameter is nil, the main bundle is used.
// Releases resources in response to memory pressure (e.g. memory warning), reloading from the bundle when necessary.
+ (UINib *)nibWithNibName:(NSString *)name bundle:(nullable NSBundle *)bundleOrNil;

// If the bundle parameter is nil, the main bundle is used.
+ (UINib *)nibWithData:(NSData *)data bundle:(nullable NSBundle *)bundleOrNil;

// Returns an array containing the top-level objects from the NIB.
// The owner and options parameters may both be nil.
// If the owner parameter is nil, connections to File's Owner are not permitted.
// Options are identical to the options specified with -[NSBundle loadNibNamed:owner:options:]
- (NSArray *)instantiateWithOwner:(nullable id)ownerOrNil options:(nullable NSDictionary *)optionsOrNil;
@end
代码语言:javascript
复制
@available(iOS 4.0, *)
open class UINib : NSObject {

    
    // If the bundle parameter is nil, the main bundle is used.
    // Releases resources in response to memory pressure (e.g. memory warning), reloading from the bundle when necessary.
    public /*not inherited*/ init(nibName name: String, bundle bundleOrNil: Bundle?)

    
    // If the bundle parameter is nil, the main bundle is used.
    public /*not inherited*/ init(data: Data, bundle bundleOrNil: Bundle?)

    
    // Returns an array containing the top-level objects from the NIB.
    // The owner and options parameters may both be nil.
    // If the owner parameter is nil, connections to File's Owner are not permitted.
    // Options are identical to the options specified with -[NSBundle loadNibNamed:owner:options:]
    open func instantiate(withOwner ownerOrNil: Any?, options optionsOrNil: [AnyHashable : Any]? = nil) -> [Any]
}
UINib Demo
代码语言:javascript
复制
let testViewNib = UINib.init(nibName: "TestView", bundle: Bundle.main)
代码语言:javascript
复制
func loadTestView() {
    let testView = UINib.instantiate(withOwner: nil, options: nil)[0] as! UIView
    view.addSubview(testView)
}
使用与 UIViewController 子类源文件关联的 xib
Demo HomeViewController.swift <==> HomeController.xib
代码语言:javascript
复制
let homeVC = HomeViewController()
代码语言:javascript
复制
class HomeViewController {
    var aName: String?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: "HomeController", bundle: nil)
    }

    init(aName: String) {
        name = aName
        super.init(nibName: "HomeController", bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

嵌套 xib

https://github.com/iOSDevLog/iOSDevLog/tree/master/228.%20NestedXib

图片上传失败请。参考 http://iosdevlog.com/ios/2017/12/19/ios-ui-interface-builder.html

使用 storyboard

代码语言:javascript
复制
@available(iOS 5.0, *)
open class UIStoryboard : NSObject {

    
    public /*not inherited*/ init(name: String, bundle storyboardBundleOrNil: Bundle?)

    
    open func instantiateInitialViewController() -> UIViewController?

    open func instantiateViewController(withIdentifier identifier: String) -> UIViewController
}

storyboard Demo

代码语言:javascript
复制
extension UIViewController {
    class func storyboardID() -> String {
        return String(describing: self)
    }
}

let userStoryBoard = UIStoryboard(name: "User", bundle: nil)
let profileVC = userStoryBoard.instantiateInitialViewController(withIdentifier: ProfileController.storyboardID())

第3章 全面学习 xib


Autoresizing

Autoresizing

默认选中左,上。

对应代码为:

代码语言:javascript
复制
testView.autoresizingMask = [.flexibleRightMargin, .flexibleBottomMargin]

外框的 上、下、左、右如果选中,则UIView的边框与父View边框距离保持不变。

中间带箭头的选中表示UIView边框是随屏幕尺寸变化的。 否则UIView大小保持不变。

也可以看右侧的动画查看显示效果。

第4章 在 Interface Builder 中使用 Auto Layout


在 IB 中使用 Auto Layout 的优缺点

  • 设置约束十分简单
  • 如果约束不恰当,IB 提供很好的实时反馈
  • 如果约束不恰当,IB 可以帮忙改正。改正操作十分简单、方便、快捷。
  • 难以理解

约束

Auto Layout 的数学公式

代码语言:javascript
复制
item1.attribute1 = multiplier * item2.attribute2 + constant

约束属性

代码语言:javascript
复制
public enum NSLayoutAttribute : Int {
    case left
    case right
    case top
    case bottom
    case leading
    case trailing
    case width
    case height
    case centerX
    case centerY
    case lastBaseline
    @available(iOS 8.0, *)
    case firstBaseline
    @available(iOS 8.0, *)
    case leftMargin
    @available(iOS 8.0, *)
    case rightMargin
    @available(iOS 8.0, *)
    case topMargin
    @available(iOS 8.0, *)
    case bottomMargin
    @available(iOS 8.0, *)
    case leadingMargin
    @available(iOS 8.0, *)
    case trailingMargin
    @available(iOS 8.0, *)
    case centerXWithinMargins
    @available(iOS 8.0, *)
    case centerYWithinMargins
    case notAnAttribute
}

约束关系

代码语言:javascript
复制
public enum NSLayoutRelation : Int {
    case lessThanOrEqual
    case equal
    case greaterThanOrEqual
}

约束的优先级

代码语言:javascript
复制
public struct UILayoutPriority : RawRepresentable, Equatable, Hashable {
    public init(_ rawValue: Float)
    public init(rawValue: Float)
}

extension UILayoutPriority {
    @available(iOS 6.0, *)
    public static let required: UILayoutPriority

    @available(iOS 6.0, *)
    public static let defaultHigh: UILayoutPriority // This is the priority level with which a button resists compressing its content.

    @available(iOS 6.0, *)
    public static let defaultLow: UILayoutPriority // This is the priority level at which a button hugs its contents horizontally.

    @available(iOS 6.0, *)
    public static let fittingSizeLevel: UILayoutPriority // When you send -[UIView systemLayoutSizeFittingSize:], the size fitting most closely to the target size (the argument) is computed.  UILayoutPriorityFittingSizeLevel is the priority level with which the view wants to conform to the target size in that computation.  It's quite low.  It is generally not appropriate to make a constraint at exactly this priority.  You want to be higher or
    lower.
}

Instrinsic Size 固有尺寸

默认设置了 Width 和 Height

Content Compression Resistance 压缩阻力

Content Hugging 内容吸附

NSLayoutConstraint 与 @IBOutlet 连线

设置约束的方法

  1. 在 IB 中设置 - 推荐
  2. 苹果原生 API - 最复杂,强烈不推荐
  3. 用 VFL (Visual Format Language) 设置约束 - 不推荐
  4. 第三方库(Masonry等)设置约束 - 代码设置最简单、最常用 推荐(如果不熟悉 Auto Layout)

UIStackView

Axis

  • Vertical: 竖直布局
  • Horizontal: 水平布局

Alignment

  • Fill
  • Top
  • Leading
  • Center
  • Bottom
  • Trailing
  • First Baseline
  • Last Base Line

Distribution

  • Fill
  • Fill Equal
  • Fill Proportionally
  • Equal Spacing
  • Equal Centering

Space

Baseline Relative

FDStackView

NSUUID https://gist.github.com/OliverLetterer/4643294

Auto Layout 的异类 - UIScrollView

UIScrollView 的子 View 需要设置 6 个约束

代码语言:javascript
复制
scrollView.contentSize.width = subView.leading + subView.width + subView.trailing;
scrollView.contentSize.height = subView.top + subView.height+ subView.bottom;

设置 ScrollView 的子 View 约束时一定要让系统确定 ScrollView 的 contentSize。

第5章 storyboard 全面学习


Extra View

segue

Embed Segue

Unwind Segue

Launch Screen

https://github.com/iOSDevLog/iOSDevLog/tree/master/229.%20ScreenLunch

代码语言:javascript
复制
@interface AppDelegate ()
            
@property (nonatomic, strong) UIWindow* launchWindow;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.launchWindow = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
    self.launchWindow.hidden = NO;
    self.launchWindow.windowLevel = UIWindowLevelNormal + 1;
    self.launchWindow.rootViewController = [UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil].instantiateInitialViewController;
    [UIView animateWithDuration:3 delay:0.5 options: UIViewAnimationOptionCurveEaseInOut animations:^{
        self.launchWindow.alpha = 0;
    } completion:^(BOOL finished) {
        self.launchWindow.hidden = YES;
        self.launchWindow.windowLevel = UIWindowLevelNormal - 1;
        self.launchWindow.alpha = 1;
    }];
    
    return YES;
}
@end
代码语言:javascript
复制
var launchWindow: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    launchWindow = UIWindow(frame: UIScreen.main.bounds)
    launchWindow?.windowLevel = UIWindowLevelNormal + 1
    launchWindow?.isHidden = false
    launchWindow?.rootViewController = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()
    UIView.animate(withDuration: 0.5, delay: 3, options: .curveEaseInOut, animations: {
        self.launchWindow?.alpha = 0
    }) { (finish) in
        if finish {
            self.launchWindow?.isHidden = true
            self.launchWindow?.windowLevel = UIWindowLevelNormal - 1
            self.launchWindow?.alpha = 1
        }
    }
    return true
}

第6章 Interface Builder 进阶


Use Trait Variations

设备

竖屏

横屏

3.5 iPhone

wC hR

wC hC

4.0 iPhone

wC hR

wC hC

4.7 iPhone

wC hR

wC hC

5.5 iPhone

wC hR

wR hC

iPad

wR hR

wR hR

User Define Runtime Attribute

IB 中的类型

Swift

Objective-C

Boolean

Bool

BOOL

Number

+

+

String

String

NSString

Localized String

String

NSString

Point

CGPoint

CGPoint

Size

CGSize

CGSize

Rect

CGRect

CGRect

Range

Range

NSRange

Color

UIColor

UIColor

Image

UIImage

UIImage

Nil

Nil

Nil

Number 在 Swift 里面可以对应 Int、Double、Float。 在 Objective-C 里面可以对应 NSInteger、NSNumber 等。

代码语言:javascript
复制
extension UIView {
    var borderColor: UIColor {
        set {
            self.layer.borderColor = newValue.cgColor
        }
        get {
            return UIColor.init(cgColor: self.layer.borderColor!)
        }
    }
}

IB 文件的加载过程

Bundle 和 UINib

  1. 将 nib 加载到内存
  2. 解固化并实例化 nib 文件里对应的对象
  3. 建立 connections (outlet、action)
  4. 调用 awakeFromNib() 方法
  5. 将 nib 中可见的控件显示出来

本地化

两种策略

  1. App 本地化跟随系统语言
  2. App 内部有一个可以设置语言的选项

本地化介绍

Base

文本的本地化

  1. 利用 NSLocalizedString。 新建 Localizable.strings 文件

Localizable.strings(English)

代码语言:javascript
复制
"test" = "hello world";

Localizable.strings(Chinese(Simplified))

代码语言:javascript
复制
"test" = "你好,世界";
代码语言:javascript
复制
override func viewDidLoad() {
    super.viewDidLoad()
    // Localizable.string
    testLabel.text = NSLocalizedString("test", comment: "")
    // Home.strings
    // testLabel.text = NSLocalizedString("test", tableName: "Home", comment: "")
}

Info.plist 的本地化

新建 InfoPlist.strings,在 Show the File inspector 点击 Localize...

InfoPlist.strings(English)

代码语言:javascript
复制
CFBundleName = "hello world";
CFBundleDisplayName = "hello world";

InfoPlist.strings(Chinese(Simplified))

代码语言:javascript
复制
CFBundleName = "你好,世界";
CFBundleDisplayName = "你好,世界";

图片资源的本地化

  • 方法1

Localizable.strings(English)

代码语言:javascript
复制
"testImageName" = "1";

Localizable.strings(Chinese(Simplified))

代码语言:javascript
复制
"testImageName" = "2";
代码语言:javascript
复制
testImageView.image = UIImage.init(named: NSLocalizedString("testImageName", comment: "")
  • 方法2

选中图片,Show the File inspector 点击 localize...,替换 zh-Hans.lproj 中的资源文件。

App 内设置语言的本地化

https://github.com/iOSDevLog/iOSDevLog/tree/master/230.%20Localizations

代码语言:javascript
复制
extension Bundle {
    class func loadLocalizableString(languageBundleName: String, key: String) -> String? {
        let languageBundlePath = Bundle.main.path(forResource: languageBundleName, ofType: "lproj")
        
        guard languageBundlePath != nil else {
            return nil
        }
        
        let languageBundle = Bundle.init(path: languageBundlePath!)
        guard languageBundle != nil else {
            return nil
        }
        
        let value = languageBundle?.localizedString(forKey: key, value: "", table: "")
        
        return value
    }
}

func changeLanguage() {
    let kTestKey = "testKey"
    
    switch selectIndex {
    case 0:
        testLabel.text = Bundle.loadLocalizableString(languageBundleName: Language.simplifiedChinese.rawValue, key: kTestKey)
        break
    case 1:
        testLabel.text = Bundle.loadLocalizableString(languageBundleName: Language.english.rawValue, key: kTestKey)
        break
    case 2:
        testLabel.text = Bundle.loadLocalizableString(languageBundleName: Language.japanese.rawValue, key: kTestKey)
        break
    case 3:
        testLabel.text = Bundle.loadLocalizableString(languageBundleName: Language.korea.rawValue, key: kTestKey)
        break
    default:
        break
    }
}

Storyboard Reference 的使用

使用 RBStoryboardLink https://github.com/rob-brown/RBStoryboardLink

用 Object 重构 "神VC"

代码量庞大、结构臃肿、可维护性差的 VC。

使用 Object

  • 通常 VC 会成为很多对象的 delegate,需要处理很多回调。用 Object 替 VC 实现 delegate。
  • 将一些能用需求或交互模块化在对应的 Object 里。将需求或交互与 VC 解耦。

用 External Object 重构 VC

只能在于 xib

IB 中的关键字总结

Swift

  • @IBAction
  • @IBOutlet
  • @IBDesignable
  • @IBInspectable

Objective-C

  • IBAction
  • IBOutlet
  • IB_DESIGNABLE
  • IBInspectable
  • IBOutletCollection(ClassName)

@IBDesignalbe

可以不运行程序的情况下把源文件中的一些代码实时渲染到 IB 中,但是源文件必须是 UIView 或者 NSView 的子类。

代码语言:javascript
复制
prepareForInterfaceBuild()

只需要将实时渲染的代码放到 prepareForInterfaceBuild() 方法中就可以了,该方法并不会在程序运行时调用。

@IBInspectable

@IBInspectable 修饰的属性会显示在 IB 的 Show the Attributes inspector

代码语言:javascript
复制
extension UIView {
    private struct AssociatedKeys {
        static var name: String?
    }
    
    // 存储属性
    @IBInspectable var name: String {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.name) as! String
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.name, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }
    
    
    // 计算属性
    @IBInspectable var borderColor: UIColor {
        set {
            self.layer.borderColor = newValue.cgColor
        }
        get {
            return UIColor.init(cgColor: self.layer.borderColor!)
        }
    }
}

第7章 在 Interface Builder 开发中的技巧和 Bug


调整 View 的尺寸,使它与显示内容的尺寸相适应

comment + =

查看各个 View 之间的距离

选中 View, 按住 option,悬停在其它 View 上。

在 IB 中添加参考线

Editor -> Guides -> Add Horizontal Line

command + -

Editor -> Guides -> Add Vertical Line

command + ctrl + |

快速调整底层被挡住的 View 的位置

快速查看 View 的 UI 层次关系

command + shift + right click

连线小技巧

两个窗口

使用吸管快速设置颜色

IB 中的复制与粘贴

command + c

command + v

利用 Media Library 快速设置图片

IB 开发中遇到的一些小 bug

最好的做法就是重启 Xcode。

  • 无法连线

IB 文件是否与源文件关联

  • @IBAction 红色提示

先在源文件中定义好方法,再从源文件 到 IB 文件进行 连线

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.12.20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第1章 Interface Bundle 概要
    • Bundle
      • nib
        • Interface Builder 的优点
          • Interface Builder 的缺点
            • Interface Builder 学习的特点
              • Interface Builder 的发展
                • CocoaPods
                  • Podfile文件与CocoaPods的三种依赖方式
                    • podspec文件
                    • 第2章 使用 Interface Builder
                      • 解决冲突
                        • 关联 xib 文件与源文件
                        • @IBOutlet 与 @IBAction
                      • 设计模式之MVC
                        • 理解 File's Owner
                          • 关联 xib 文件与 UIViewController 子类的源文件
                            • 使用 xib
                              • 使用与UIView子类源文件关联的xib
                            • 使用 storyboard
                            • 第3章 全面学习 xib
                              • Autoresizing
                                • 在 IB 中使用 Auto Layout 的优缺点
                            • 第4章 在 Interface Builder 中使用 Auto Layout
                              • 约束
                                • Auto Layout 的数学公式
                                • 约束属性
                                • 约束关系
                                • 约束的优先级
                                • Instrinsic Size 固有尺寸
                                • Content Compression Resistance 压缩阻力
                                • Content Hugging 内容吸附
                                • NSLayoutConstraint 与 @IBOutlet 连线
                              • 设置约束的方法
                                • UIStackView
                                  • FDStackView
                                  • NSUUID https://gist.github.com/OliverLetterer/4643294
                                • Auto Layout 的异类 - UIScrollView
                                • 第5章 storyboard 全面学习
                                  • Extra View
                                    • segue
                                      • Embed Segue
                                      • Unwind Segue
                                    • Launch Screen
                                    • 第6章 Interface Builder 进阶
                                      • Use Trait Variations
                                        • User Define Runtime Attribute
                                          • IB 文件的加载过程
                                            • 本地化
                                              • 本地化介绍
                                              • 文本的本地化
                                              • Info.plist 的本地化
                                              • 图片资源的本地化
                                            • App 内设置语言的本地化
                                              • Storyboard Reference 的使用
                                                • 用 Object 重构 "神VC"
                                                  • 使用 Object
                                                • 用 External Object 重构 VC
                                                  • IB 中的关键字总结
                                                    • @IBDesignalbe
                                                    • @IBInspectable
                                                • 第7章 在 Interface Builder 开发中的技巧和 Bug
                                                  • 调整 View 的尺寸,使它与显示内容的尺寸相适应
                                                    • 查看各个 View 之间的距离
                                                      • 在 IB 中添加参考线
                                                        • 快速调整底层被挡住的 View 的位置
                                                          • 快速查看 View 的 UI 层次关系
                                                            • 连线小技巧
                                                              • 使用吸管快速设置颜色
                                                                • IB 中的复制与粘贴
                                                                  • 利用 Media Library 快速设置图片
                                                                    • IB 开发中遇到的一些小 bug
                                                                    领券
                                                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档