Comments (3)
延伸阅读:
- Ray Wenderlich: How To Make a Custom Control Tutorial: A Reusable Slider
- Objc.io: Custom Controls
- Knob: Subclassing UIControl with Swift
- API Reference: UIControl
- Apple doc: Target-Action Mechanism
- Matt Gemmell’s 25 rules of API design
- Apple doc: Drawing and Printing Guide for iOS
- API Reference: UIResponder
from iosdevlevelingup.
How To Make a Custom Control Tutorial: A Reusable Slider 的学习总结
目录
- 学习笔记
- 问题与收获
学习笔记
-
Choose a existing class for custom control to subclass or extend: You’ll be using the target-action pattern in this custom control, so
UIControl
will serve as a great starting point. -
Before you write any code for your control, you should add your control to the view controller so that you can watch the evolution of the control.
-
API Design: Before you add the visual elements to your control, you’ll need a few properties to keep track of the various pieces of information that are stored in your control.
-
Well-designed controls should define some default property values.
-
Images vs. CoreGraphics
5.1 Images: Simple to use, but it’s difficult to modify the control from code.
5.2 Core Graphics: More flexible, but you have to write the rendering code yourself.
5.3 Apple tend to opt for using images in their controls.(You could see thatUISlider
uses images to configure appearance from API and by debugging view hierarchy.) -
Adding Interactive Logic: store which thumb is being dragged, and reflect that in the UI.
-
Adding Touch Handlers: add the ability for the user to drag the slider thumbs around.
7.1UIControl
provides several methods for tracking touches, so we can override these methods to add interaction logic.
7.2beginTrackingWithTouch(:with:)
7.3continueTrackingWithTouch(:with:)
7.4endTrackingWithTouch(:with:)
-
Change Notifications
- NSNotification,** Key-Value-Observing (KVO): If you look at the UIKit controls, you’ll find they don’t use NSNotification or encourage the use of KVO, so for consistency with UIKit you can exclude those two options.
- the delegate pattern**:- A protocol can contain a number of methods.
- A delegate method can take any number of parameters.
- A control only accept a single delegate instance.
- the target-action pattern:
- The target-action pattern is provided by the UIControl base class.
- You can provide multiple targets to control actions.
- while it is possible to create custom events (see UIControlEventApplicationReserved) the number of custom events is limited to 4.
- Control actions do not have the ability to send any information with the event.
- The key differences between the above two patterns are as follows:
- Multicast:
one-to-one
vs.one-to-many
- Flexibility:
can pass extra information
vs.cannot pass extra information directly
- Multicast:
- NSNotification,** Key-Value-Observing (KVO): If you look at the UIKit controls, you’ll find they don’t use NSNotification or encourage the use of KVO, so for consistency with UIKit you can exclude those two options.
-
Modifying Your Control With Core Graphics: override
draw(in:)
method -
Handling Changes to Control Properties: implement property observers that update the control’s frame or drawing.
-
Test:
When you are developing a custom control, it’s your responsibility to exercise all of its properties and visually verify the results.
A good way to approach this is to create a visual test harness with various buttons and sliders, each of which connected to a different property of the control.
That way you can modify the properties of your custom control in real time — and see the results in real time. -
Where To Go From Here?
- Documentation: A good practice is to provide public API documentation, at a minimum, for all publicly shared code. This means documenting all public classes and properties.
- **Robustness**: You need to ensure that the control state always remains valid — despite what some silly coder tries to do to it.
- **API Design**: Creating a flexible, intuitive and robust API will ensure that your control can be widely used, as well as wildly popular. See *[Matt Gemmell’s 25 rules of API design](http://www.mattgemmell.com/api-design/)*.
- **Sharing**: GitHub, CocoaPods, [Cocoa Controls](https://www.cocoacontrols.com)
问题与收获
1.平时自己写的自定义 UI 控件一般都是继承 UIView
,这个教程让我进一步见识了 UIControl
的价值,还是得多看看官方的 API Reference 和 Guides 。
2.一个功能、一个控件、一个框架的实现都不是一蹴而就的,这是一个不断进化、完善的过程。
3.要想受欢迎,一个框架/库的 API 一定要设计好,使用简单、功能齐全、文档清晰,推荐阅读 Matt Gemmell’s 25 rules of API design。
4.实现一个控件的外观一般有两种方式:
- 图片:开发简单,只需要 UI 设计好图片资源直接替换就行了,缺点在于不方便开发人员自定义,缺乏灵活度。
- 用系统的库(CoreGraphics、 OpenGL ES)来绘制:完全由开发人员的代码来控制,灵活度高,方便自定义,缺点在于需要耗费开发资源,也就是说要写很多代码。
5.写代码前需要想清楚要做哪几件事,比如写好一个自定义 control,就需要考虑:要继承什么类、API 怎么设计、外观展示怎么实现(subviews 和 sublayers、images 和 CoreGraphics)、交互逻辑怎么处理(touch 事件)、事件和数据怎么传递(target-action等)。
6.事件传递的几种方式:
- delegate:一般情况下只支持一对一(当然你也可以采用一些特殊方式来解决),优点在于,方法数和参数值不限,定义清晰,内存管理方面相比 block 也有很多优势,缺点是代码比量较多,结构松散。
- notification 和 KVO:支持多对多,可以传值,APP 内任何地方都可以监听、发送通知,但是滥用的话很容易出现难以追踪的 bug,而且性能上会比 delegate 低(因为在 Objective-C 的运行时会动态生成类)。
- target-action:一般用于 control 类的控件,支持一对多,但是传值不太方便,一般需要通过访问
sender
参数才能间接同步到数据。 - block:代码结构紧凑,支持一对多(搞一个 blocks 数组),但是用的不好容易出现内存泄漏。
7.自测:一个好的程序应该是经过广泛覆盖的测试的,写程序总会有 bug 的,谁也无法保证他自己写过的代码永远不会出 bug,所以写完代码后减低 bug 出现率的最佳方式是 realtime test。
8.鲁棒性:优秀的程序员一定不能不考虑代码的健壮性,各种边界情况以及框架使用者的错误使用方式都要考虑,比如需要用断言提前判断是否传入空值,预防使用者设置最大值比最小值还小的情况。
9.文档:代码除了写了给机器运行之外,还要给人去读的,对于那些开源软件来说,需要更加注意这点,好的文档就如同产品说明书一般,使用者用起来也方便,YYKit 的代码就是最佳典范。
10.分享:把有价值的代码分享出去,既能帮助别人快速开发,又能提供给别人参考学习,除此之外,还能得到不同人的意见和建议、反馈(issue、pull request)。还有一点就是被人 star 的满足感。
11.更多 Swift 相关的问题见练习代码中的 // TODO:
标记。
from iosdevlevelingup.
Custom Controls 的学习总结
学习笔记
1. Overview of the View Hierarchy
- UIResponder
- What's a responder's responsibility
- Why
UIResponder
is a separate class, and not merged intoUIView
? - First responder and responder chain
- Customize the input methods
- UIView
- What's a view's responsibility
- A common misconception is that this area is defined by the view’s frame
- Add gesture recognizers to views
- UIControl
- Building on views, the
UIControl
class adds more support for interactivity. - It has the target/action pattern
- Some scenarios of not using custom controls
- Building on views, the
2. Rendering(TODO: What, Why, How)
- Custom Rendering
- You probably want to avoid doing rendering on the CPU, but instead offload it to the GPU. There is one rule of thumb to achieve this: try to avoid
drawRect:
, and instead compose your custom views out of existing views. See Getting Pixels onto the Screen - Often, the quickest way to render something is just by using image views. Most of what you can achieve with view's layer property will be faster than drawing your own things using Core Graphics.
- Nonetheless, as always, it is important to profile your code.
- By using stretchable images together with your image views, you can also greatly improve performance. See Taming UIButton, a comment by Andy Matuschak
- If you are processing images, you can also often get away with letting the GPU do that for you by using
Core Image
orOpenGL
, instead of doing it withCore Graphics
.
- You probably want to avoid doing rendering on the CPU, but instead offload it to the GPU. There is one rule of thumb to achieve this: try to avoid
- Custom Drawing
- Generate an image, and then cache that, either on disk or in memory
- If your content is very dynamic, you can maybe use
Core Animation
- if it doesn’t work, go for
Core Graphics
- If you really want to get close to the metal, it is not that hard to use
GLKit
and rawOpenGL
, but it does require a lot of work - If you do choose to override
drawRect:
, make sure to take a look at content modes
3. Custom Interaction:communication strategies between views and their owners
-
Overview
- By subclassing
UIControl
, you can fire events using the target action mechanism - To respond to touches, you almost always want to use gesture recognizers
- if you want to go low-level, you can still override the methods
touchesBegan
,touchesMoved
, andtouchesEnded
to get access to the raw touches - To separate the gesture handling from your custom view or view controller, it is almost always more appropriate to create a gesture recognizer subclass
- Communicating back the value to the classes that own them:
- target-action
- delegates
- blocks
- key-value observing
- notifications.
- By subclassing
-
Use Target-Action
- Advantages: You only need to do very little in your custom view subclass, and you automatically get support for multiple targets.
-
Use Delegates
- Advantages: You can do more complicated things than just letting the owner know that the value changed
- Drawbacks:
- You might need to check if your delegate implements the method you want to call
- You can typically only have one delegate (or you need to create an array of delegates)
-
Use Blocks
- Advantages: You can group related code together in the view controller
- Drawbacks:
- It is important to check if the block is set, because calling a block that is not set will crash
- You typically have only one block per action
- Be aware of the possibility of leading to retain cycle
- Once the block bodies get out of hand, you will also probably extract them to methods of their own, and then you might as well have used delegates
-
Use KVO
- Use this for observing
- It’s a nice pattern to decouple things
- You also need to remove the observer when you don't need it anymore.
- Observing multiple children from the same object quickly gets messy
- ReactiveCocoa
- THObserversAndBinders(more lightweight)
-
Use Notifications
- Advantages: quite decoupled, a very loose coupling
- Drawbacks: lose type safety, you get a notification object in your callback, and the compiler can’t check if the types between the notification sender and the notification receiver match
4. Accessibility
- The standard iOS controls provided by Apple are all accessible.
- For detail, see Accessibility Programming Guide explains how to make the controls accessible
- If you have a view that has multiple elements inside it that should be accessible, but are not subviews, then you can implement the UIAccessibilityContainer protocol for your view
5. Localization
- The most straightforward thing to localize in your custom views is string contents
- Another really helpful tool in localization is Auto Layout, using Auto Layout to handling the label's size instead of hardcoding.
- For detail, see Internationalization and Localization Guide
6. Testing
- Unit Testing
- UIAutomation
- Taking screenshots
- Make sure your views are really pixel-perfect by automatically comparing them with the design specification
- Automatically generate the screenshots for the App Store
问题与收获
1.UIResponder 与 UIResponder Chain #51
2.touch 事件的处理,自定义 gesture recognizer #52
3.屏幕渲染原理和绘制,渲染视图时影响性能的主要因素是什么 #48
4.再次回顾了几种不同的事件回调方式的对比
5.有空研究一下 ReactiveCocoa #22
6.相比第一篇文章,这篇文章不是教程,更偏向于理论,理解起来不太直观,但是其中谈到了很多技术点,很值得研究
7.单元测试、UI 自动化测试基本上很少用,不知道国内有多少团队用了 #24
from iosdevlevelingup.
Related Issues (20)
- NSMapTable 和 NSHashTable HOT 1
- 计算机组成原理 HOT 2
- button 文字有两行时,图片上文字下,文字宽度有问题 HOT 2
- Protocol Buffer ("protobuf") HOT 1
- 英文文章阅读笔记 HOT 2
- WWDC HOT 6
- 如何提升技术深度? HOT 1
- 如何自学计算机专业课程?
- Lua 语言
- Lightweight Generics HOT 1
- Flutter HOT 2
- 关于WebViewJavascriptBridge的一点疑问 HOT 3
- 周报(2019) HOT 25
- 热修复
- runloop HOT 1
- 汇编语言 HOT 1
- 爬虫与反爬虫 HOT 1
- UICollection View not Scrolling vertically
- A/B Testing HOT 1
- IM 即时通讯 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from iosdevlevelingup.