我想通过递归重写代码,这样可以无限制地遍历大纲中的所有子代。
我当前的代码最多可以遍历3个级别(而且我知道我可以增加更多的循环并增加遍历的最大级别),但是我认为可以更高效地重写。我想知道重写traverseOutline(outline:PDFOutline?)方法更好。
import UIKit
import PDFKit
protocol OutlineDelegate: class {
func goTo(page: PDFPage)
}
class OutlineViewController {
@IBOutlet weak var tableView: UITableView!
weak var delegate: OutlineDelegate?
var outline: PDFOutline?
var bookmarks = [Bookmark]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
traverseOutline(outline: outline)
tableView.reloadData()
}
func traverseOutline (outline: PDFOutline?) {
// 1st level
guard let outline = outline else { return}
for i in 0...outlineCycleItems(outline) {
if let bookmark = Bookmark(outline: outline, index: i) {
bookmarks.append(bookmark)
let subOutline = outline.child(at: i)
// 2nd level
for j in 0...outlineCycleItems(subOutline!) {
if let bookmark = Bookmark(outline: subOutline, index: j) {
bookmark.name = "- " + bookmark.name!
bookmarks.append(bookmark)
let subSubOutline = subOutline?.child(at: j)
// 3rd level
for k in 0...outlineCycleItems(subSubOutline!) {
if let bookmark = Bookmark(outline: subSubOutline, index: k){
bookmark.name = "-- " + bookmark.name!
bookmarks.append(bookmark)
}
}
}
}
}
}
}
func outlineCycleItems(_ outline: PDFOutline) -> Int {
let amount = outline.numberOfChildren
if amount == 0 {
return amount
} else {
return amount - 1
}
}
}
extension OutlineViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return bookmarks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChapterCell", for: indexPath) as! ItemOutlineCell
cell.configureCell(name: bookmarks[indexPath.row].name!)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.goTo(page: bookmarks[indexPath.row].link!)
}
}
class ItemOutlineCell: UITableViewCell {
@IBOutlet weak var chapterName: UILabel!
func configureCell (name: String){
chapterName.text = name
}
}
class Bookmark {
var link: PDFPage?
var name: String?
init(link: PDFPage, name: String) {
self.link = link
self.name = name
}
init?(outline: PDFOutline?, index: Int) {
guard let child = outline?.child(at: index) else {
return nil
}
link = child.destination?.page
name = child.label
}
}
感谢@Erik的主要思想,我使用一个函数重写了这一点:
override func viewDidAppear(_ animated: Bool) {
if let outline = outline {
traverseOutline(outline: outline, currentLevel: 0)
tableView.reloadData()
}
}
func traverseOutline (outline: PDFOutline, currentLevel: Int) {
for i in 0...outlineCycleItems(outline) {
if let bookmark = Bookmark(outline: outline, index: i) {
let dashes = String(repeating: "-", count: currentLevel)
bookmark.name = dashes + bookmark.name!
bookmarks.append(bookmark)
let subOutline = outline.child(at: i)
traverseOutline(outline: subOutline!, currentLevel: currentLevel + 1)
}
}
}
答案 0 :(得分:2)
您可以通过添加一个不断调用自身的额外函数来使代码真正地递归。我将第一级保持独立,因为它与其他级别略有不同。在您的原始功能中:
func traverseOutline (outline: PDFOutline?) {
guard let outline = outline else { return}
for i in 0...outlineCycleItems(outline) {
if let bookmark = Bookmark(outline: outline, index: i) {
bookmarks.append(bookmark)
let subOutline = outline.child(at: i)
recursiveTraverse(outline: subOutline)
}
}
}
然后定义一个名为recursiveTraverse
的新函数:
func recursiveTraverse(outline:PDFOutline){
for j in 0...outlineCycleItems(subOutline!) {
if let bookmark = Bookmark(outline: outline, index: j) {
bookmark.name = "- " + bookmark.name!
bookmarks.append(bookmark)
recursiveTraverse(outline: outline.child(at: j))
}
}
}
通过为for循环中的每个单独的轮廓调用自身,将继续下降。仅当它无法在路径端点上的任何轮廓之外制作书签时(当if语句对循环中的所有轮廓都为false时),它才会在某个路径上停止。