Skip to content

Commit

Permalink
Merge pull request #36 from kazuhiro4949/feature/fixCompleteHandlerOf…
Browse files Browse the repository at this point in the history
…ContentVC

fix complete handler for setting contentOffset
  • Loading branch information
kazuhiro4949 committed Jan 7, 2018
2 parents 50abeeb + 8f1361e commit f51e36f
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 41 deletions.
43 changes: 19 additions & 24 deletions PagingKit/PagingContentViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,15 @@ public class PagingContentViewController: UIViewController {
public func reloadData(with page: Int = 0, completion: (() -> Void)? = nil) {
removeAll()
initialLoad(with: page)
UIView.animate(
withDuration: 0,
animations: { [weak self] in
UIView.pk.catchLayoutCompletion(
layout: { [weak self] in
self?.view.setNeedsLayout()
self?.view.layoutIfNeeded()
},
completion: { [weak self] (finish) in
self?.scroll(to: page, animated: false)
completion?()
completion: { [weak self] _ in
self?.scroll(to: page, animated: false) { _ in
completion?()
}
}
)
}
Expand All @@ -182,24 +182,25 @@ public class PagingContentViewController: UIViewController {
/// - Parameters:
/// - page: A index defining an content of the content view controller.
/// - animated: true if the scrolling should be animated, false if it should be immediate.
public func scroll(to page: Int, animated: Bool) {
public func scroll(to page: Int, animated: Bool, completion: ((Bool) -> Void)? = nil) {
delegate?.contentViewController(viewController: self, willBeginPagingAt: leftSidePageIndex, animated: animated)

loadPagesIfNeeded(page: page)
leftSidePageIndex = page

delegate?.contentViewController(viewController: self, willFinishPagingAt: leftSidePageIndex, animated: animated)
scroll(to: page, animated: animated) { [weak self] (finished) in
move(to: page, animated: animated) { [weak self] (finished) in
guard let _self = self, finished else { return }
completion?(finished)
_self.delegate?.contentViewController(viewController: _self, didFinishPagingAt: _self.leftSidePageIndex, animated: animated)
}
}

private func scroll(to page: Int, animated: Bool, completion: @escaping (Bool) -> Void) {
private func move(to page: Int, animated: Bool, completion: @escaping (Bool) -> Void) {
let offsetX = scrollView.bounds.width * CGFloat(page)
if animated {
stopScrolling()
performSystemAnimation(
UIView.pk.performSystemAnimation(
{ [weak self] in
self?.scrollView.contentOffset = CGPoint(x: offsetX, y: 0)
},
Expand All @@ -208,8 +209,14 @@ public class PagingContentViewController: UIViewController {
}
)
} else {
scrollView.contentOffset = CGPoint(x: offsetX, y: 0)
completion(true)
UIView.pk.catchLayoutCompletion(
layout: { [weak self] in
self?.scrollView.contentOffset = CGPoint(x: offsetX, y: 0)
},
completion: { _ in
completion(true)
}
)
}
}

Expand Down Expand Up @@ -375,15 +382,3 @@ extension PagingContentViewController: UIScrollViewDelegate {
explicitPaging = nil
}
}

// MARK:- Private top-level function

private func performSystemAnimation(_ animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil) {
UIView.perform(
.delete,
on: [],
options: UIViewAnimationOptions(rawValue: 0),
animations: animations,
completion: completion
)
}
31 changes: 31 additions & 0 deletions PagingKit/PagingKitProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,34 @@ extension PagingKitProxy where Base == UIColor.Type {
)
}
}

extension PagingKitProxy where Base == UIView.Type {
/// call this function to catch completion handler of layoutIfNeeded()
///
/// - Parameters:
/// - layout: method which has layoutIfNeeded()
/// - completion: completion handler of layoutIfNeeded()
func catchLayoutCompletion(layout: @escaping () -> Void, completion: @escaping (Bool) -> Void) {
UIView.animate(withDuration: 0, animations: {
layout()
}) { (finish) in
completion(finish)
}
}


/// perform system like animation
///
/// - Parameters:
/// - animations: animation Handler
/// - completion: completion Handler
func performSystemAnimation(_ animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil) {
UIView.perform(
.delete,
on: [],
options: UIViewAnimationOptions(rawValue: 0),
animations: animations,
completion: completion
)
}
}
18 changes: 2 additions & 16 deletions PagingKit/PagingMenuViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,12 @@ public class PagingMenuViewController: UIViewController {
public func reloadData(with preferredFocusIndex: Int? = nil, completionHandler: ((Bool) -> Void)? = nil) {
let selectedIndex = preferredFocusIndex ?? currentFocusedIndex ?? 0
menuView.focusView.selectedIndex = selectedIndex
catchLayoutCompletion(
UIView.pk.catchLayoutCompletion(
layout: { [weak self] in
self?.menuView.reloadData()
},
completion: { [weak self] (finish) in
catchLayoutCompletion(
UIView.pk.catchLayoutCompletion(
layout: { [weak self] in
self?.scroll(index: selectedIndex, percent: 0, animated: false)
},
Expand Down Expand Up @@ -329,17 +329,3 @@ extension PagingMenuViewController: PagingMenuViewDataSource {
return dataSource!.menuViewController(viewController: self, cellForItemAt: index)
}
}


/// call this function to catch completion handler of layoutIfNeeded()
///
/// - Parameters:
/// - layout: method which has layoutIfNeeded()
/// - completion: completion handler of layoutIfNeeded()
func catchLayoutCompletion(layout: @escaping () -> Void, completion: @escaping (Bool) -> Void) {
UIView.animate(withDuration: 0, animations: {
layout()
}) { (finish) in
completion(finish)
}
}
62 changes: 61 additions & 1 deletion PagingKitTests/PagingContentViewControllerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,61 @@ class PagingContentViewControllerTests: XCTestCase {
self.dataSource = dataSource
}

func testHookCompletionHandlerAfterReloadData() {
guard let pagingContentViewController = pagingContentViewController else {
XCTFail()
return
}

let dataSource = PagingContentVcDataSourceSpy(count: 100)
pagingContentViewController.dataSource = dataSource
pagingContentViewController.loadViewIfNeeded()

do {
let expectation = XCTestExpectation(description: "index: 4")
pagingContentViewController.reloadData(with: 50, completion: {
let expectedOffsetX = pagingContentViewController.scrollView.bounds.width * 50
XCTAssertEqual(
pagingContentViewController.scrollView.contentOffset,
CGPoint(x: expectedOffsetX, y: 0),
"PagingContentViewController has completely finished reloading"
)
expectation.fulfill()
})
wait(for: [expectation], timeout: 1)
}

do {
let expectation = XCTestExpectation(description: "index: 2")
pagingContentViewController.reloadData(with: 98, completion: {
let expectedOffsetX = pagingContentViewController.scrollView.bounds.width * 98
XCTAssertEqual(
pagingContentViewController.scrollView.contentOffset,
CGPoint(x: expectedOffsetX, y: 0),
"PagingContentViewController has completely finished reloading"
)
expectation.fulfill()
})
wait(for: [expectation], timeout: 1)
}

do {
let expectation = XCTestExpectation(description: "index: 5")
pagingContentViewController.reloadData(with: 40, completion: {
let expectedOffsetX = pagingContentViewController.scrollView.bounds.width * 40
XCTAssertEqual(
pagingContentViewController.scrollView.contentOffset,
CGPoint(x: expectedOffsetX, y: 0),
"PagingContentViewController has completely finished reloading"
)
expectation.fulfill()
})
wait(for: [expectation], timeout: 1)
}

self.dataSource = dataSource
}

func testContentOffsetRatioInScrolling() {
let expectation = XCTestExpectation(description: "finish reloadData")
let dataSource = PagingContentVcDataSourceSpy()
Expand Down Expand Up @@ -133,7 +188,12 @@ class PagingContentVcDataSourceMock: NSObject, PagingContentViewControllerDataSo
}

class PagingContentVcDataSourceSpy: NSObject, PagingContentViewControllerDataSource {
let vcs: [UIViewController] = Array(repeating: UIViewController(), count: 5)
init(count: Int = 5) {
vcs = Array(repeating: UIViewController(), count: count)
super.init()
}

let vcs: [UIViewController]

func numberOfItemsForContentViewController(viewController: PagingContentViewController) -> Int {
return vcs.count
Expand Down

0 comments on commit f51e36f

Please sign in to comment.