One, foreword
In the last post, we completed our first custom component, The Circular Countdown Progress Bar, which supports both CocoaPods and SPM, but does not form a separate library. As mentioned in this article, we will introduce components to the AD page to improve the page; Of course, if this article just improves the page, it might be too much, after all, it’s relatively easy to use. Therefore, I also incidentally put the eighth, although given the source code, but no analysis of the content (timer) analysis, as well as through the code to write constraints need to pay attention to the point, and the reason is also analyzed to you.
Two, improve the advertising page
To be lazy, I used SPM’s native integration approach, just dragging the entire directory into the project and adding the framework.
Open AdvertiseViewController, import & lazy Init
import CircleProgressView
class AdvertiseViewController: BaseViewController {
.
// Lazily initializes the View and does not write the location and size as given by the following constraints
lazy var progress: CircleProgressView = CircleProgressView(frame: CGRect.zero)
.
}
Copy the code
2.2 place the circular countdown progress bar control
class AdvertiseViewController: BaseViewController {
func countDown(a) {
progress.translatesAutoresizingMaskIntoConstraints = false
// Allow the user to click and skip to the next page
progress.isUserInteractionEnabled = true
progress.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.terminer)))
view.addSubview(progress)
/ / constraints:
// 1.
// 2. Top margin = 50
// 3. Trailing margin = -30
NSLayoutConstraint.activate([
progress.widthAnchor.constraint(equalToConstant: 64.0),
progress.heightAnchor.constraint(equalToConstant: 64.0),
progress.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
progress.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30)]).}}Copy the code
2.3. Modify viewDidLoad to start countdown & Start animation
class AdvertiseViewController: BaseViewController {
override func viewDidLoad(a) {
super.viewDidLoad()
view.backgroundColor = .kRed
countDown() // timeCountDown() = countDown()
}
func countDown(a) {
.
// Start animation, countdown time, animation from 0.0 -> 1.0
progress.setProgress(1.0, duration: Double(seconds), animated: true)
// Start the countdown
timeCountDown()
}
}
Copy the code
2.4 in the countdown process, our reading seconds should also keep changing
class AdvertiseViewController: BaseViewController {
func timeCountDown(a) {
timer.schedule(deadline: .now(), repeating: .seconds(1))
timer.setEventHandler(handler: {
DispatchQueue.main.async { [weak self] in
// If the timer is less than or equal to 0, end the timer and switch between two Windows
if self!.seconds < = 0 {
self!.terminer()
} else {
// In the countdown, keep setting the contents of the label
self!.progress.setContent(String(self!.seconds))
}
self!.seconds - = 1
}
})
timer.resume()
}
}
Copy the code
2.5. Finally, modify our termination method (add @objc)
class AdvertiseViewController: BaseViewController {
@objc func terminer(a) {
.}}Copy the code
Three, constraints layout matters needing attention
I don’t know if you noticed the following code:
class AdvertiseViewController: BaseViewController {
func countDown(a) {
progress.translatesAutoresizingMaskIntoConstraints = false
.
view.addSubview(progress)
NSLayoutConstraint.activate([
.
])
.}}Copy the code
Before the code sets constraints, we all need to view the translatesAutoresizingMaskIntoConstraints attribute is set to false? Of course, if you’ve been using xiBs for layout and setting constraints, you probably won’t notice, but you probably know. Also, even with XIBS, there is a code layout problem, so if you tell me that everyone does it, so you do it, well, this article will take a look at it and help you better understand why.
In general, we create a view in two ways:
- Through the code to create the view (default is OC translatesAutoresizingMaskIntoConstraints: YES/Swift: true, hereinafter the same).
- To create the view through the IB (translatesAutoresizingMaskIntoConstraints default is (autoresize layout: YES, autolayout layout: NO));
In the above code, we use constrained layout (Autolayout).
Why use translatesAutoresizingMaskIntoConstraints constraint layout, is set to false (OC: NO)?
Because translatesAutoresizingMaskIntoConstraints meant the frame layout will be automatically converted to constraint layout, the result of the conversion is needed for this view is automatically add all constraints, If we add our own constraints to the view, we are bound to have constraint conflicts.
Four, common timer (only for use, not to expand)
Timers commonly used in iOS are as follows:
- NSTimer;
- CADisplayLink;
- The GCD.
- Simulation in other ways
advantages | disadvantages | |
---|---|---|
NSTimer | Using a simple | The timing is not accurate because of Runloop |
CADisplayLink | High precision | The CPU load will affect the triggering event, and the triggering event will cause frame drop if the triggering event is longer than the triggering interval. |
GCD | More accurate | Basically unaffected by other influences |
Our AD page, the timer is actually GCD, it is a low-level way, rely on the system kernel timer, as for the other, this article will not expand, the mainstream commonly used general preferred GCD, because more accurate, and will not have cyclic reference, memory leaks and other problems.
After Swift4, creating GCD timer is much easier, just one sentence:
// Timer associates a queue (global.global(),.main, or something else)
// After that, timer.seteventhandler can put the event to be processed into this queue
lazy var timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
Copy the code
Later, we can call schedule to set when timer starts, how long interval, whether delay is allowed and how long delay is acceptable:
// Deadline is the start time, for example: start immediately.now() // repeating is the interval time, for.never or.default it will only trigger once // leeway in some cases (e.g. @available(swift 4) public func Schedule (deadline: DispatchTime, repeating interval: DispatchTimeInterval = .never, leeway: DispatchTimeInterval = .nanoseconds(0))Copy the code
Since our timer has already been created but is not yet running, the method to start it is:
timer.resume()
Copy the code
Suspension is:
timer.suspend()
Copy the code
Cancellation is:
timer.cancel()
Copy the code
At this point, [double window + advertising page + the first component: circular countdown progress bar] we are completely finished sharing, next, start to enter our body: home page. (I have been very busy recently, working on the overall solution of big data offline + real-time, as well as the operation and maintenance system; -_ -!!!!!! The first content on the front page may be a few days late, sorry)
All source code so far: Passgate
If you have any questions, please contact us. Thank you!
This article is participating in the “Nuggets 2021 Spring Recruitment Campaign”, click to see the details of the campaign