- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章IOS实战之自定义转场动画详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
转场动画这事,说简单也简单,可以通过presentviewcontroller:animated:completion:和dismissviewcontrolleranimated:completion:这一组函数以模态视图的方式展现、隐藏视图。如果用到了navigationcontroller,还可以调用pushviewcontroller:animated:和popviewcontroller这一组函数将新的视图控制器压栈、弹栈.
下图中所有转场动画都是自定义的动画,这些效果如果不用自定义动画则很难甚至无法实现:
由于录屏的原因,有些效果无法完全展现,比如它其实还支持横屏.
自定义转场动画的效果实现起来比较复杂,如果仅仅是拷贝一份能够运行的代码却不懂其中原理,就有可能带来各种隐藏的bug。本文由浅入深介绍下面几个知识:
1、传统的基于闭包的实现方式及其缺点 2、自定义present转场动画 3、交互式(interactive)转场动画 4、转场协调器与uimodalpresentationcustom 5、uinavigationcontroller转场动画 。
在开始正式的教程前,您首先需要下载demo,在代码面前文字是苍白的,demo中包含的注释足以解释本文所有的知识点。其次,您还得了解这几个背景知识.
from和to 在代码和文字中,经常会出现fromview和toview。如果错误的理解它们的含义会导致动画逻辑完全错误。fromview表示当前视图,toview表示要跳转到的视图。如果是从a视图控制器present到b,则a是from,b是to。从b视图控制器dismiss到a时,b变成了from,a是to。用一张图表示:
presented和presengting 这也是一组相对的概念,它容易与fromview和toview混淆。简单来说,它不受present或dismiss的影响,如果是从a视图控制器present到b,那么a总是presentedviewcontroller,b总是presentingviewcontroller.
modalpresentationstyle 这是一个枚举类型,表示present时动画的类型。其中可以自定义动画效果的只有两种:fullscreen和custom,两者的区别在于fullscreen会移除fromview,而custom不会。比如文章开头的gif中,第三个动画效果就是custom.
基于block的动画 最简单的转场动画是使用transitionfromviewcontroller方法:
这个方法虽然已经过时,但是对它的分析有助于后面知识的理解。它一共有6个参数,前两个表示从哪个vc开始,跳转到哪个vc,中间两个参数表示动画的时间和选项。最后两个参数表示动画的具体实现细节和回调闭包.
这六个参数其实就是一次转场动画所必备的六个元素。它们可以分为两组,前两个参数为一组,表示页面的跳转关系,后面四个为一组,表示动画的执行逻辑.
这个方法的缺点之一是可自定义程度不高(在后面您会发现能自定义的不仅仅是动画方式),另一个缺点则是重用性不好,也可以说是耦合度比较大.
在最后两个闭包参数中,可以预见的是fromviewcontroller和toviewcontroller参数都会被用到,而且他们是动画的关键。假设视图控制器a可以跳转到b、c、d、e、f,而且跳转动画基本相似,您会发现transitionfromviewcontroller方法要被复制多次,每次只会修改少量内容.
自定义present转场动画 出于解耦和提高可自定义程度的考虑,我们来学习转场动画的正确使用姿势.
首先要了解一个关键概念:转场动画代理,它是一个实现了uiviewcontrollertransitioningdelegate协议的对象。我们需要自己实现这个对象,它的作用是为uikit提供以下几个对象中的一个或多个:
1、animator:
它是实现了uiviewcontrolleranimatedtransitioning协议的对象,用于控制动画的持续时间和动画展示逻辑,代理可以为present和dismiss过程分别提供animator,也可以提供同一个animator.
交互式animator:和animator类似,不过它是交互式的,后面会有详细介绍 。
presentation控制器:
它可以对present过程更加彻底的自定义,比如修改被展示视图的大小,新增自定义视图等,后面会有详细介绍.
在这一小节中,我们首先介绍最简单的animator。回顾一下转场动画必备的6个元素,它们被分为两组,彼此之间没有关联。animator的作用等同于第二组的四个元素,也就是说对于同一个animator,可以适用于a跳转b,也可以适用于a跳转c。它表示一种通用的页面跳转时的动画逻辑,不受限于具体的视图控制器.
如果您读懂了这段话,整个自定义的转场动画逻辑就很清楚了,以视图控制器a跳转到b为例:
用具体的例子解释就是:
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 这个类相当于a
class
crossdissolvefirstviewcontroller: uiviewcontroller, uiviewcontrollertransitioningdelegate {
// 这个对象相当于b
crossdissolvesecondviewcontroller.transitioningdelegate = self
// 点击按钮触发的函数
func animationbuttondidclicked() {
self.presentviewcontroller(crossdissolvesecondviewcontroller,
animated:
true
, completion: nil)
}
// 下面这两个函数定义在uiviewcontrollertransitioningdelegate协议中
// 用于为present和dismiss提供animator
func animationcontrollerforpresentedcontroller(presented: uiviewcontroller, presentingcontroller presenting: uiviewcontroller, sourcecontroller source: uiviewcontroller) -> uiviewcontrolleranimatedtransitioning? {
// 也可以使用crossdissolveanimator,动画效果各有不同
// return crossdissolveanimator()
return
halfwayspringanimator()
}
func animationcontrollerfordismissedcontroller(dismissed: uiviewcontroller) -> uiviewcontrolleranimatedtransitioning? {
return
crossdissolveanimator()
}
}
|
动画的关键在于animator如何实现,它实现了uiviewcontrolleranimatedtransitioning协议,至少需要实现两个方法,我建议您仔细阅读animatetransition方法中的注释,它是整个动画逻辑的核心:
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
class
halfwayspringanimator: nsobject, uiviewcontrolleranimatedtransitioning {
/// 设置动画的持续时间
func transitionduration(transitioncontext: uiviewcontrollercontexttransitioning?) -> nstimeinterval {
return
2
}
/// 设置动画的进行方式,附有详细注释,demo中其他地方的这个方法不再解释
func animatetransition(transitioncontext: uiviewcontrollercontexttransitioning) {
let fromviewcontroller = transitioncontext.viewcontrollerforkey(uitransitioncontextfromviewcontrollerkey)
let toviewcontroller = transitioncontext.viewcontrollerforkey(uitransitioncontexttoviewcontrollerkey)
let containerview = transitioncontext.containerview()
// 需要关注一下from/to和presented/presenting的关系
// for a presentation:
// fromview = the presenting view.
// toview = the presented view.
// for a dismissal:
// fromview = the presented view.
// toview = the presenting view.
var fromview = fromviewcontroller?.view
var toview = toviewcontroller?.view
// ios8引入了viewforkey方法,尽可能使用这个方法而不是直接访问controller的view属性
// 比如在form sheet样式中,我们为presentedviewcontroller的view添加阴影或其他decoration,animator会对整个decoration view
// 添加动画效果,而此时presentedviewcontroller的view只是decoration view的一个子视图
if
transitioncontext.respondstoselector(selector(
"viewforkey:"
)) {
fromview = transitioncontext.viewforkey(uitransitioncontextfromviewkey)
toview = transitioncontext.viewforkey(uitransitioncontexttoviewkey)
}
// 我们让toview的origin.y在屏幕的一半处,这样它从屏幕的中间位置弹起而不是从屏幕底部弹起,弹起过程中逐渐变为不透明
toview?.frame = cgrectmake(fromview!.frame.origin.x, fromview!.frame.maxy / 2, fromview!.frame.width, fromview!.frame.height)
toview?.alpha = 0.0
// 在present和,dismiss时,必须将toview添加到视图层次中
containerview?.addsubview(toview!)
let transitionduration = self.transitionduration(transitioncontext)
// 使用spring动画,有弹簧效果,动画结束后一定要调用completetransition方法
uiview.animatewithduration(transitionduration, delay: 0, usingspringwithdamping: 0.6, initialspringvelocity: 0, options: .curvelinear, animations: { () ->
void
in
toview!.alpha = 1.0
// 逐渐变为不透明
toview?.frame = transitioncontext.finalframeforviewcontroller(toviewcontroller!)
// 移动到指定位置
}) { (finished:
bool
) ->
void
in
let wascancelled = transitioncontext.transitionwascancelled()
transitioncontext.completetransition(!wascancelled)
}
}
}
|
animatetransition方法的核心则是从转场动画上下文获取必要的信息以完成动画。上下文是一个实现了uiviewcontrollercontexttransitioning的对象,它的作用在于为animatetransition方法提供必备的信息。您不应该缓存任何关于动画的信息,而是应该总是从转场动画上下文中获取(比如fromview和toview),这样可以保证总是获取到最新的、正确的信息.
获取到足够信息后,我们调用uiview.animatewithduration方法把动画交给core animation处理。千万不要忘记在动画调用结束后,执行completetransition方法.
本节的知识在demo的cross dissolve文件夹中有详细的代码。其中有两个animator文件,这说明我们可以为present和dismiss提供同一个animator,或者分别提供各自对应的animator。如果两者动画效果类似,您可以共用同一个animator,惟一的区别在于:
如果您被前面这一大段代码和知识弄晕了,或者暂时用不到这些具体的知识,您至少需要记住自定义动画的基本原理和流程:
交互式(interactive)转场动画 刚刚我们说到,设置了toviewcontroller的transitioningdelegate属性并且present时,uikit会从代理处获取animator,其实这里还有一个细节:uikit还会调用代理的interactioncontrollerforpresentation:方法来获取交互式控制器,如果得到了nil则执行非交互式动画,这就回到了上一节的内容.
如果获取到了不是nil的对象,那么uikit不会调用animator的animatetransition方法,而是调用交互式控制器(还记得前面介绍动画代理的示意图么,交互式动画控制器和animator是平级关系)的startinteractivetransition:方法.
所谓的交互式动画,通常是基于手势驱动,产生一个动画完成的百分比来控制动画效果(文章开头的gif中第二个动画效果)。整个动画不再是一次性、连贯的完成,而是在任何时候都可以改变百分比甚至取消。这需要一个实现了uipercentdriveninteractivetransition协议的交互式动画控制器和animator协同工作。这看上去是一个非常复杂的任务,但uikit已经封装了足够多细节,我们只需要在交互式动画控制器和中定义一个时间处理函数(比如处理滑动手势),然后在接收到新的事件时,计算动画完成的百分比并且调用updateinteractivetransition来更新动画进度即可.
用下面这段代码简单表示一下整个流程(删除了部分细节和注释,请不要以此为正确参考),完整的代码请参考demo中的interactivity文件夹:
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// 这个相当于fromviewcontroller
class
interactivityfirstviewcontroller: uiviewcontroller {
// 这个相当于toviewcontroller
lazy var interactivitysecondviewcontroller: interactivitysecondviewcontroller = interactivitysecondviewcontroller()
// 定义了一个interactivitytransitiondelegate类作为代理
lazy var customtransitiondelegate: interactivitytransitiondelegate = interactivitytransitiondelegate()
override func viewdidload() {
super.viewdidload()
setupview()
// 主要是一些ui控件的布局,可以无视其实现细节
/// 设置动画代理,这个代理比较复杂,所以我们新建了一个代理对象而不是让self作为代理
interactivitysecondviewcontroller.transitioningdelegate = customtransitiondelegate
}
// 触发手势时,也会调用animationbuttondidclicked方法
func interactivetransitionrecognizeraction(sender: uiscreenedgepangesturerecognizer) {
if
sender.state == .began {
self.animationbuttondidclicked(sender)
}
}
func animationbuttondidclicked(sender: anyobject) {
self.presentviewcontroller(interactivitysecondviewcontroller, animated:
true
, completion: nil)
}
}
|
非交互式的动画代理只需要为present和dismiss提供animator即可,但是在交互式的动画代理中,还需要为present和dismiss提供交互式动画控制器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class
interactivitytransitiondelegate: nsobject, uiviewcontrollertransitioningdelegate {
func animationcontrollerforpresentedcontroller(presented: uiviewcontroller, presentingcontroller presenting: uiviewcontroller, sourcecontroller source: uiviewcontroller) -> uiviewcontrolleranimatedtransitioning? {
return
interactivitytransitionanimator(targetedge: targetedge)
}
func animationcontrollerfordismissedcontroller(dismissed: uiviewcontroller) -> uiviewcontrolleranimatedtransitioning? {
return
interactivitytransitionanimator(targetedge: targetedge)
}
/// 前两个函数和淡入淡出demo中的实现一致
/// 后两个函数用于实现交互式动画
func interactioncontrollerforpresentation(animator: uiviewcontrolleranimatedtransitioning) -> uiviewcontrollerinteractivetransitioning? {
return
transitioninteractioncontroller(gesturerecognizer: gesturerecognizer, edgefordragging: targetedge)
}
func interactioncontrollerfordismissal(animator: uiviewcontrolleranimatedtransitioning) -> uiviewcontrollerinteractivetransitioning? {
return
transitioninteractioncontroller(gesturerecognizer: gesturerecognizer, edgefordragging: targetedge)
}
}
|
animator中的代码略去,它和非交互式动画中的animator类似。因为交互式的动画只是一种锦上添花,它必须支持非交互式的动画,比如这个例子中,点击按钮依然出发的是非交互式的动画,只是手势滑动才会触发交互式动画.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class
transitioninteractioncontroller: uipercentdriveninteractivetransition {
/// 当手势有滑动时触发这个函数
func gesturerecognizedidupdate(gesturerecognizer: uiscreenedgepangesturerecognizer) {
switch
gesturerecognizer.state {
case
.began:
break
case
.changed: self.updateinteractivetransition(self.percentforgesture(gesturerecognizer))
//手势滑动,更新百分比
case
.ended:
// 滑动结束,判断是否超过一半,如果是则完成剩下的动画,否则取消动画
if
self.percentforgesture(gesturerecognizer) >= 0.5 {
self.finishinteractivetransition()
}
else
{
self.cancelinteractivetransition()
}
default
: self.cancelinteractivetransition()
}
}
private
func percentforgesture(gesture: uiscreenedgepangesturerecognizer) -> cgfloat {
let percent = 根据gesture计算得出
return
percent
}
}
|
交互式动画是在非交互式动画的基础上实现的,我们需要创建一个继承自uipercentdriveninteractivetransition类型的子类,并且在动画代理中返回这个类型的实例对象.
在这个类型中,监听手势(或者下载进度等等)的时间变化,然后调用percentforgesture方法更新动画进度即可.
转场协调器与uimodalpresentationcustom 在进行转场动画的同时,您还可以进行一些同步的,额外的动画,比如文章开头gif中的第三个例子。presentedview和presentingview可以更改自身的视图层级,添加额外的效果(阴影,圆角)。uikit使用转成协调器来管理这些额外的动画。您可以通过需要产生动画效果的视图控制器的transitioncoordinator属性来获取转场协调器,转场协调器只在转场动画的执行过程中存在.
想要完成gif中第三个例子的效果,我们还需要使用uimodalpresentationstyle.custom来代替.fullscreen。因为后者会移除fromviewcontroller,这显然不符合需求.
当present的方式为.custom时,我们还可以使用uipresentationcontroller更加彻底的控制转场动画的效果。一个 presentation controller具备以下几个功能:
您可以认为,. fullscreen以及其他present风格都是swift为我们实现提供好的,它们是.custom的特例。而.custom允许我们更加自由的定义转场动画效果.
uipresentationcontroller提供了四个函数来定义present和dismiss动画开始前后的操作:
下面的代码简要描述了gif中第三个动画效果的实现原理,您可以在demo的custom presentation文件夹下查看完成代码:
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// 这个相当于fromviewcontroller
class
custompresentationfirstviewcontroller: uiviewcontroller {
// 这个相当于toviewcontroller
lazy var custompresentationsecondviewcontroller: custompresentationsecondviewcontroller = custompresentationsecondviewcontroller()
// 创建presentationcontroller
lazy var custompresentationcontroller: custompresentationcontroller = custompresentationcontroller(presentedviewcontroller: self.custompresentationsecondviewcontroller, presentingviewcontroller: self)
override func viewdidload() {
super.viewdidload()
setupview()
// 主要是一些ui控件的布局,可以无视其实现细节
// 设置转场动画代理
custompresentationsecondviewcontroller.transitioningdelegate = custompresentationcontroller
}
override func didreceivememorywarning() {
super.didreceivememorywarning()
// dispose of any resources that can be recreated.
}
func animationbuttondidclicked() {
self.presentviewcontroller(custompresentationsecondviewcontroller, animated:
true
, completion: nil)
}
}
|
重点在于如何实现custompresentationcontroller这个类:
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
class
custompresentationcontroller: uipresentationcontroller, uiviewcontrollertransitioningdelegate {
var presentationwrappingview: uiview?
// 这个视图封装了原视图,添加了阴影和圆角效果
var dimmingview: uiview? = nil
// alpha为0.5的黑色蒙版
// 告诉uikit为哪个视图添加动画效果
override func presentedview() -> uiview? {
return
self.presentationwrappingview
}
}
// 四个方法自定义转场动画发生前后的操作
extension custompresentationcontroller {
override func presentationtransitionwillbegin() {
// 设置presentationwrappingview和dimmingview的ui效果
let transitioncoordinator = self.presentingviewcontroller.transitioncoordinator()
self.dimmingview?.alpha = 0
// 通过转场协调器执行同步的动画效果
transitioncoordinator?.animatealongsidetransition({ (context: uiviewcontrollertransitioncoordinatorcontext) ->
void
in
self.dimmingview?.alpha = 0.5
}, completion: nil)
}
/// present结束时,把dimmingview和wrappingview都清空,这些临时视图用不到了
override func presentationtransitiondidend(completed:
bool
) {
if
!completed {
self.presentationwrappingview = nil
self.dimmingview = nil
}
}
/// dismiss开始时,让dimmingview完全透明,这个动画和animator中的动画同时发生
override func dismissaltransitionwillbegin() {
let transitioncoordinator = self.presentingviewcontroller.transitioncoordinator()
transitioncoordinator?.animatealongsidetransition({ (context: uiviewcontrollertransitioncoordinatorcontext) ->
void
in
self.dimmingview?.alpha = 0
}, completion: nil)
}
/// dismiss结束时,把dimmingview和wrappingview都清空,这些临时视图用不到了
override func dismissaltransitiondidend(completed:
bool
) {
if
completed {
self.presentationwrappingview = nil
self.dimmingview = nil
}
}
}
extension custompresentationcontroller {
}
|
除此以外,这个类还要处理子视图布局相关的逻辑。它作为动画代理,还需要为动画提供animator对象,详细代码请在demo的custom presentation文件夹下阅读.
uinavigationcontroller转场动画 到目前为止,所有转场动画都是适用于present和dismiss的,其实uinavigationcontroller也可以自定义转场动画。两者是平行关系,很多都可以类比过来:
1
2
3
4
5
6
7
8
9
10
|
class
fromviewcontroller: uiviewcontroller, uinavigationcontrollerdelegate {
let toviewcontroller: toviewcontroller = toviewcontroller()
override func viewdidload() {
super.viewdidload()
setupview()
// 主要是一些ui控件的布局,可以无视其实现细节
self.navigationcontroller.delegate = self
}
}
|
与present/dismiss不同的时,现在视图控制器实现的是uinavigationcontrollerdelegate协议,让自己成为navigationcontroller的代理。这个协议类似于此前的uiviewcontrollertransitioningdelegate协议.
fromviewcontroller实现uinavigationcontrollerdelegate协议的具体操作如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func navigationcontroller(navigationcontroller: uinavigationcontroller,
animationcontrollerforoperation operation: uinavigationcontrolleroperation,
fromviewcontroller fromvc: uiviewcontroller,
toviewcontroller tovc: uiviewcontroller)
-> uiviewcontrolleranimatedtransitioning? {
if
operation == .push {
return
pushanimator()
}
if
operation == .pop {
return
popanimator()
}
return
nil;
}
|
至于animator,就和此前没有任何区别了。可见,一个封装得很好的animator,不仅能在present/dismiss时使用,甚至还可以在push/pop时使用.
uinavigationcontroller也可以添加交互式转场动画,原理也和此前类似.
总结 对于非交互式动画,需要设置presentedviewcontroller的transitioningdelegate属性,这个代理需要为present和dismiss提供animator。在animator中规定了动画的持续时间和表现逻辑.
对于交互式动画,需要在此前的基础上,由transitioningdelegate属性提供交互式动画控制器。在控制器中进行事件处理,然后更新动画完成进度.
对于自定义动画,可以通过uipresentationcontroller中的四个函数自定义动画执行前后的效果,可以修改presentedviewcontroller的大小、外观并同步执行其他的动画.
自定义动画的水还是比较深,本文仅适合做入门学习用,欢迎互相交流.
最后此篇关于IOS实战之自定义转场动画详解的文章就讲到这里了,如果你想了解更多关于IOS实战之自定义转场动画详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
实战-行业攻防应急响应 简介: 服务器场景操作系统 Ubuntu 服务器账号密码:root/security123 分析流量包在/home/security/security.pcap 相
背景 最近公司将我们之前使用的链路工具切换为了 OpenTelemetry. 我们的技术栈是: OTLP C
一 同一类的方法都用 synchronized 修饰 1 代码 package concurrent; import java.util.concurrent.TimeUnit; public c
一 简单例子 1 代码 package concurrent.threadlocal; /** * ThreadLocal测试 * * @author cakin */ public class T
1. 问题背景 问题发生在快递分拣的流程中,我尽可能将业务背景简化,让大家只关注并发问题本身。 分拣业务针对每个快递包裹都会生成一个任务,我们称它为 task。task 中有两个字段需要
实战环境 elastic search 8.5.0 + kibna 8.5.0 + springboot 3.0.2 + spring data elasticsearch 5.0.2 +
Win10下yolov8 tensorrt模型加速部署【实战】 TensorRT-Alpha 基于tensorrt+cuda c++实现模型end2end的gpu加速,支持win10、
yolov8 tensorrt模型加速部署【实战】 TensorRT-Alpha 基于tensorrt+cuda c++实现模型end2end的gpu加速,支持win10、linux,
目录如下: 为什么需要自定义授权类型? 前面介绍OAuth2.0的基础知识点时介绍过支持的4种授权类型,分别如下: 授权码模式 简化模式 客户端模式 密码模式
今天这篇文章介绍一下如何在修改密码、修改权限、注销等场景下使JWT失效。 文章的目录如下: 解决方案 JWT最大的一个优势在于它是无状态的,自身包含了认证鉴权所需要的所有信息,服务器端
前言 大家好,我是捡田螺的小男孩。(求个星标置顶) 我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下。本文将分四个方案,讨论如何优化MySQL百万数
前言 大家好,我是捡田螺的小男孩。 平时我们写代码呢,多数情况都是流水线式写代码,基本就可以实现业务逻辑了。如何在写代码中找到乐趣呢,我觉得,最好的方式就是:使用设计模式优化自己
我们先讲一些arm汇编的基础知识。(我们以armv7为例,最新iphone5s上的64位暂不讨论) 基础知识部分: 首先你介绍一下寄存器: r0-r3:用于函数参数及返回值的传递 r4-r6
一 同一类的静态方法都用 synchronized 修饰 1 代码 package concurrent; import java.util.concurrent.TimeUnit; public
DRF快速写五个接口,比你用手也快··· 实战-DRF快速写接口 开发环境 Python3.6 Pycharm专业版2021.2.3 Sqlite3 Django 2.2 djangorestfram
一 添加依赖 org.apache.thrift libthrift 0.11.0 二 编写 IDL 通过 IDL(.thrift 文件)定义数据结构、异常和接口等数据,供各种编程语言使用 nam
我正在阅读 Redis in action e-book关于semaphores的章节.这是使用redis实现信号量的python代码 def acquire_semaphore(conn, semn
自定义控件在WPF开发中是很常见的,有时候某些控件需要契合业务或者美化统一样式,这时候就需要对控件做出一些改造。 目录 按钮设置圆角
师父布置的任务,让我写一个服务练练手,搞清楚socket的原理和过程后跑了一个小demo,很有成就感,代码内容也比较清晰易懂,很有教育启发意义。 代码 ?
? 1 2
我是一名优秀的程序员,十分优秀!