From 9cc7829005e3aba79750b63d3f6101671ba7eb81 Mon Sep 17 00:00:00 2001 From: LianJun <1586008023@qq.com> Date: Sun, 30 Jul 2023 20:09:26 +0800 Subject: [PATCH] 20230730.20 --- Fourm/Fourm.xcodeproj/project.pbxproj | 8 +- Fourm/Fourm/DataFile/New Group/File | 7 ++ Fourm/Fourm/FrameFile/BasicData.swift | 25 ++++- Fourm/Fourm/FrameFile/ControlBuild.swift | 8 +- Fourm/Fourm/FrameFile/ControlExtension.swift | 3 +- Fourm/Fourm/FrameFile/EssayControl copy.swift | 103 ++++++++++++++---- Fourm/Fourm/FrameFile/UserDefaults.swift | 6 + Fourm/Fourm/ViewController.swift | 2 +- .../CollectionViewController.swift | 38 ++++--- .../DiscussViewController.swift | 6 +- .../LearningViewController.swift | 58 +++++----- .../ViewController/SearchViewController.swift | 50 +++++---- .../EssayViewController.swift | 51 +++++---- .../SettingViewController.swift | 61 ++++++++++- .../EssayThemeViewController.swift | 77 ++++++++++++- 15 files changed, 365 insertions(+), 138 deletions(-) diff --git a/Fourm/Fourm.xcodeproj/project.pbxproj b/Fourm/Fourm.xcodeproj/project.pbxproj index 0487b9e..fd474a2 100644 --- a/Fourm/Fourm.xcodeproj/project.pbxproj +++ b/Fourm/Fourm.xcodeproj/project.pbxproj @@ -647,8 +647,10 @@ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UIStatusBarStyle = ""; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -675,8 +677,10 @@ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UIStatusBarStyle = ""; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/Fourm/Fourm/DataFile/New Group/File b/Fourm/Fourm/DataFile/New Group/File index 6b6a534..c295690 100644 --- a/Fourm/Fourm/DataFile/New Group/File +++ b/Fourm/Fourm/DataFile/New Group/File @@ -9,6 +9,8 @@ @backDeployed要求当前所在类型与修饰内容的访问权限不低于public。 @backDeployed适用于计算属性与方法。 #code Swift + + import Foundation import UIKit @@ -32,6 +34,11 @@ func essayInterfaceBuild0(_ essayData: String, _ VC: UIViewController) { } + + + + + ##code # [weak self]改变 Swift 5.3 之后 self 可以在闭包中有条件省略,Swift 5.8 之后类中的[weak self]也可以省略 self。 diff --git a/Fourm/Fourm/FrameFile/BasicData.swift b/Fourm/Fourm/FrameFile/BasicData.swift index ddf821c..fa0e5d0 100644 --- a/Fourm/Fourm/FrameFile/BasicData.swift +++ b/Fourm/Fourm/FrameFile/BasicData.swift @@ -10,6 +10,9 @@ struct Screen { let window = windowScene?.windows.first return window?.safeAreaInsets ?? UIEdgeInsets.zero } + static func nativeHeight() -> CGFloat { + UIScreen.main.nativeBounds.height // 与设备屏幕宽度一样宽(物理) + } static func width() -> CGFloat { UIScreen.main.bounds.width // 与设备屏幕宽度一样宽 } @@ -29,23 +32,33 @@ struct Screen { /// 选择间距相关的方法,返回CGFloat struct Spaced { + /// 屏幕边框与内容之间的间距 static func screen() -> CGFloat { - 20 // 屏幕边框与内容之间的间距 + 20 } + /// 屏幕边框与内容之间的间距,会根据安全区域自动调整 static func screenAuto() -> CGFloat { - 20 + Screen.safeAreaInsets().left // 屏幕边框与内容之间的间距,会根据安全区域自动调整 + 20 + Screen.safeAreaInsets().left } + /// 各个相邻的控件之间的间距,也用做二级标题和模块之间的间距/ static func control() -> CGFloat { - 10 // 各个相邻的控件之间的间距,也用做二级标题和模块之间的间距 + 10 } + /// 各个模块之间的间距/ static func module() -> CGFloat { - 30 // 各个模块之间的间距 + 30 } + /// 各个设置之间的间距 static func setting() -> CGFloat { - 25 // 各个设置之间的间距 + 25 } + /// 导航栏与第一个模块之间的间距 static func navigation() -> CGFloat { - 18 // 导航栏与第一个模块之间的间距 + 18 + } + /// 代码块的代码行间距 + static func codeRow() -> CGFloat { + 4 } } diff --git a/Fourm/Fourm/FrameFile/ControlBuild.swift b/Fourm/Fourm/FrameFile/ControlBuild.swift index d438689..7d8d7fc 100644 --- a/Fourm/Fourm/FrameFile/ControlBuild.swift +++ b/Fourm/Fourm/FrameFile/ControlBuild.swift @@ -151,10 +151,9 @@ extension Setting { returnDictionary["view"] = settingControl /// 控件上方的说明(`caption`)部分 - let captionLabel = UILabel().fontAdaptive(caption, font: Font.tips()) + let captionLabel = UILabel().fontAdaptive(caption, font: Font.tips(), width: Screen.basicWidth() - Spaced.screen() * 2) if !caption.isEmpty { captionLabel.frame.origin = CGPoint(x: Spaced.screen(), y: 0) - captionLabel.frame.size.width = Screen.basicWidth() - Spaced.screen() * 2 captionLabel.textColor = UIColor.black.withAlphaComponent(0.6) settingControl.addSubview(captionLabel) } @@ -217,10 +216,9 @@ extension Setting { } /// 控件下方的提示(`tips`)部分 - let tipsLabel = UILabel().fontAdaptive(tips, font: Font.tips()) + let tipsLabel = UILabel().fontAdaptive(tips, font: Font.tips(), width: Screen.basicWidth() - Spaced.screen() * 2) if !tips.isEmpty { - tipsLabel.frame.origin = CGPoint(x: Spaced.screen(), y: returnDictionary["\(control.count)"]!.frame.maxY + 6) - tipsLabel.frame.size.width = Screen.basicWidth() - Spaced.screen() * 2 + tipsLabel.frame.origin = CGPoint(x: Spaced.screen(), y: returnDictionary["\(control.count)"]!.frame.maxY + captionLabel.frame.maxY + 6) tipsLabel.textColor = UIColor.black.withAlphaComponent(0.6) settingControl.addSubview(tipsLabel) } diff --git a/Fourm/Fourm/FrameFile/ControlExtension.swift b/Fourm/Fourm/FrameFile/ControlExtension.swift index 6af9cfe..05d4159 100644 --- a/Fourm/Fourm/FrameFile/ControlExtension.swift +++ b/Fourm/Fourm/FrameFile/ControlExtension.swift @@ -27,11 +27,12 @@ extension UILabel { /// /// - Parameter text: 内容 /// - Parameter font: 字体大小 - func fontAdaptive(_ text: String, font: UIFont) -> UILabel { + func fontAdaptive(_ text: String, font: UIFont, width: CGFloat) -> UILabel { let lable = UILabel() lable.text = text lable.font = font lable.numberOfLines = 0 + lable.frame.size.width = width lable.sizeToFit() return lable } diff --git a/Fourm/Fourm/FrameFile/EssayControl copy.swift b/Fourm/Fourm/FrameFile/EssayControl copy.swift index 6a707fa..27f971a 100644 --- a/Fourm/Fourm/FrameFile/EssayControl copy.swift +++ b/Fourm/Fourm/FrameFile/EssayControl copy.swift @@ -336,7 +336,37 @@ func title3ModuleBuild(_ string: String, _ view: UIView, originY: CGFloat) -> CG func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: CGFloat, language codeLanguage: String) -> CGFloat { // 对空行进行处理 var codeStringArray = stringArray + + // 根据是否去除前后空行的设置判断 + if UserDefaults.SettingInfo.string(forKey: .essayCodeFristAndList)! == "true" { + // 去除前面的空行 + for (index, element) in codeStringArray.enumerated() { + if !element.isEmpty { + codeStringArray.removeFirst(index) + break + } + } + // 去除后面的空行 + var last = 0 + var lastBool = false + for item in codeStringArray { + last += 1 + if !item.isEmpty, lastBool { + lastBool = !lastBool + last = 0 + } else if item.isEmpty, !lastBool { + lastBool = !lastBool + last = 0 + } + } + if codeStringArray[codeStringArray.count - 1].isEmpty { + codeStringArray.removeLast(last + 1) + } + } + + // 保留中间的空行 for (index, element) in codeStringArray.enumerated() { + if element.isEmpty { codeStringArray[index] = " " } @@ -360,11 +390,10 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: // 处理代码行和行序号 var rowArray: Array = [] var codeRowMaxX = CGFloat(0) // 接收所有代码行的最大X轴坐标的属性 - let rowSpacing = CGFloat(4) // 代码行之间的间距属性 for i in 0 ..< codeStringArray.count { // 代码行部分 let codeRow = UILabel() - codeRow.frame.origin.y = i == 0 ? 10: rowArray[(i - 1) * 2].frame.maxY + rowSpacing + codeRow.frame.origin.y = i == 0 ? 10: rowArray[(i - 1) * 2].frame.maxY + Spaced.codeRow() var newCodeString = NSMutableAttributedString(string: codeStringArray[i]) switch codeLanguage { case "Swift": newCodeString = swiftCodeOptimize(attString: newCodeString) @@ -426,8 +455,12 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: for (index, element) in rowArray.enumerated() { let rowNumber = (index - 1) / 2 + 1 // 代码行的序号的具体数字 if index % 2 == 0 { - // 代码行部分 - element.frame.origin.x = rowNumberBoxWidth + 10 + // 代码行部分,判断是否有代码行前的序号以此来决定原点的X轴坐标值 + if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == "true" { + element.frame.origin.x = rowNumberBoxWidth + 10 + } else { + element.frame.origin.x = 8 + } } else { // 代码行的序号部分 switch rowNumberDigits { @@ -462,7 +495,12 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: // 设置代码(滚动)块的样式 codeScrollBox.backgroundColor = UIColor.systemFill - codeScrollBox.contentSize.width = codeRowMaxX + rowNumberBoxWidth + 15 + // 根据是否有代码块行前序号来判断代码块的contentSize + if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == "true" { + codeScrollBox.contentSize.width = codeRowMaxX + rowNumberBoxWidth + 15 + } else { + codeScrollBox.contentSize.width = codeRowMaxX + 16 + } // 代码行序号容器的样式 rowNumberBox.frame = CGRect(x: codeScrollBox.frame.origin.x, y: codeScrollBox.frame.origin.y, width: rowNumberBoxWidth + 5, height: codeScrollBox.frame.height) @@ -480,8 +518,12 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: for (index, element) in rowArray.enumerated() { let rowNumber = (index - 1) / 2 + 1 // 代码行的序号的具体数字 if index % 2 == 0 { - // 代码行部分 - element.frame.origin.x = rowNumberBoxWidth + 5 + // 代码行部分,判断是否有代码行前的序号以此来决定原点的X轴坐标值 + if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == "true" { + element.frame.origin.x = rowNumberBoxWidth + 5 + } else { + element.frame.origin.x = 8 + } } else { // 代码行的序号部分 element.frame.origin.x += 0 @@ -519,7 +561,12 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: codeScrollBox.backgroundColor = UIColor(red: 242/255.0, green: 242/255.0, blue: 247/255.0, alpha: 1.000) codeScrollBox.layer.borderWidth = 1 codeScrollBox.layer.borderColor = UIColor(red: 138/255.0, green: 138/255.0, blue: 141/255.0, alpha: 1.000).cgColor - codeScrollBox.contentSize.width = codeRowMaxX + rowNumberBoxWidth + 10 + // 根据是否有代码块行前序号来判断代码块的contentSize + if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == "true" { + codeScrollBox.contentSize.width = codeRowMaxX + rowNumberBoxWidth + 10 + } else { + codeScrollBox.contentSize.width = codeRowMaxX + 16 + } // 代码行序号容器的样式 rowNumberBox.frame = CGRect(x: codeScrollBox.frame.origin.x + 1, y: codeScrollBox.frame.origin.y + 1, width: rowNumberBoxWidth - 0.5, height: codeScrollBox.frame.height - 2) @@ -533,23 +580,29 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: rowNumberBox.backgroundColor = UIColor.white.withAlphaComponent(0) rowNumberBox.layer.masksToBounds = true - // 线条主题代码块中序号的分割竖线 - let verticalLinePath = UIBezierPath() - let anchor = rowNumberBoxWidth + codeScrollBox.frame.origin.x - verticalLinePath.move(to: CGPoint(x: anchor, y: codeScrollBox.frame.origin.y)) - verticalLinePath.addLine(to: CGPoint(x: anchor, y: codeScrollBox.frame.maxY)) - let verticalLine = CAShapeLayer() - verticalLine.path = verticalLinePath.cgPath - verticalLine.lineWidth = 0.5 - verticalLine.strokeColor = UIColor.black.withAlphaComponent(0.5).cgColor - superView.layer.addSublayer(verticalLine) + if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == "true" { + // 线条主题代码块中序号的分割竖线,根据是否显示代码行设置来判断 + let verticalLinePath = UIBezierPath() + let anchor = rowNumberBoxWidth + codeScrollBox.frame.origin.x + verticalLinePath.move(to: CGPoint(x: anchor, y: codeScrollBox.frame.origin.y)) + verticalLinePath.addLine(to: CGPoint(x: anchor, y: codeScrollBox.frame.maxY)) + let verticalLine = CAShapeLayer() + verticalLine.path = verticalLinePath.cgPath + verticalLine.lineWidth = 0.5 + verticalLine.strokeColor = UIColor.black.withAlphaComponent(0.5).cgColor + superView.layer.addSublayer(verticalLine) + } case "gorgeous": // 设置代码行和序号的样式 for (index, element) in rowArray.enumerated() { let rowNumber = (index - 1) / 2 + 1 // 代码行的序号的具体数字 if index % 2 == 0 { - // 代码行部分 - element.frame.origin.x = rowNumberBoxWidth + 12 + // 代码行部分,判断是否有代码行前的序号以此来决定原点的X轴坐标值 + if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == "true" { + element.frame.origin.x = rowNumberBoxWidth + 12 + } else { + element.frame.origin.x = 8 + } } else { // 代码行的序号部分 element.frame.origin.x += 7 @@ -585,7 +638,12 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: // 设置代码(滚动)块的样式 codeScrollBox.backgroundColor = UIColor(red: 222/255.0, green: 221/255.0, blue: 247/255.0, alpha: 1.000) - codeScrollBox.contentSize.width = codeRowMaxX + rowNumberBoxWidth + 17 + // 根据是否有代码块行前序号来判断代码块的contentSize + if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == "true" { + codeScrollBox.contentSize.width = codeRowMaxX + rowNumberBoxWidth + 17 + } else { + codeScrollBox.contentSize.width = codeRowMaxX + 16 + } // 代码行序号容器的样式 rowNumberBox.frame = CGRect(x: 7 + codeScrollBox.frame.origin.x, y: 6 + codeScrollBox.frame.origin.y, width: rowNumberBoxWidth, height: codeScrollBox.frame.height - 12) @@ -593,8 +651,7 @@ func codeModuleBuild(_ stringArray: Array, _ superView: UIView,_ pointY: rowNumberBox.backgroundColor = UIColor.systemIndigo.withAlphaComponent(0.25) rowNumberBox.layer.cornerRadius = 5 rowNumberBox.layer.masksToBounds = true - default: - break + default: break } return codeScrollBox.frame.maxY diff --git a/Fourm/Fourm/FrameFile/UserDefaults.swift b/Fourm/Fourm/FrameFile/UserDefaults.swift index 8788193..87f6620 100644 --- a/Fourm/Fourm/FrameFile/UserDefaults.swift +++ b/Fourm/Fourm/FrameFile/UserDefaults.swift @@ -24,6 +24,8 @@ extension UserDefaults { case essayTheme /// 阅读文章界面的代码块的序号行设置(`true、false`) case essayCodeNumber + /// 阅读文章界面的代码块的前后空行是否去除功能(`true、false`) + case essayCodeFristAndList } } } @@ -38,4 +40,8 @@ func initializeUserDefaults() { if UserDefaults.SettingInfo.string(forKey: .essayCodeNumber) == nil { UserDefaults.SettingInfo.set(value: "true", forKey: .essayCodeNumber) } + // 默认文章代码块前后空行是否去除为“true”,去除 + if UserDefaults.SettingInfo.string(forKey: .essayCodeFristAndList) == nil { + UserDefaults.SettingInfo.set(value: "true", forKey: .essayCodeFristAndList) + } } diff --git a/Fourm/Fourm/ViewController.swift b/Fourm/Fourm/ViewController.swift index 09d7b26..8521137 100644 --- a/Fourm/Fourm/ViewController.swift +++ b/Fourm/Fourm/ViewController.swift @@ -18,7 +18,7 @@ class ViewController: UITabBarController { initializeUserDefaults() let viewControllers = [ - UINavigationController(rootViewController: LearningViewController().withTabBarItem(title: "推荐内容", image: UIImage(systemName: "books.vertical"), selectedImage: UIImage(systemName: "books.vertical.fill"))), + UINavigationController(rootViewController: LearningViewController().withTabBarItem(title: "推荐内容", image: UIImage(systemName: "book.pages"), selectedImage: UIImage(systemName: "book.pages.fill"))), UINavigationController(rootViewController: DiscussViewController().withTabBarItem(title: "发现更多", image: UIImage(systemName: "safari"), selectedImage: UIImage(systemName: "safari.fill"))), UINavigationController(rootViewController: CollectionViewController().withTabBarItem(title: "用户与收藏", image: UIImage(systemName: "star.square.on.square"), selectedImage: UIImage(systemName: "star.square.on.square.fill"))), UINavigationController(rootViewController: SearchViewController().withTabBarItem(title: "搜索和设置", image: UIImage(systemName: "rectangle.and.hand.point.up.left"), selectedImage: UIImage(systemName: "rectangle.and.hand.point.up.left.fill"))) diff --git a/Fourm/Fourm/ViewController/CollectionViewController.swift b/Fourm/Fourm/ViewController/CollectionViewController.swift index a3dc9fa..a8e3399 100644 --- a/Fourm/Fourm/ViewController/CollectionViewController.swift +++ b/Fourm/Fourm/ViewController/CollectionViewController.swift @@ -1,15 +1,19 @@ -//// -//// CourseViewController.swift -//// CodeForum -//// -//// Created by QHuiYan on 2023/5/22. -////let array = ["收藏夹", "合集", "文章", "闲聊杂谈", "用户", "官方公示"] // +// CourseViewController.swift +// CodeForum +// +// Created by QHuiYan on 2023/5/22. +//let array = ["收藏夹", "合集", "文章", "闲聊杂谈", "用户", "官方公示"] + import UIKit + class CollectionViewController: UIViewController { - + override func viewDidLoad() { + super.viewDidLoad() + Initialize.view(self, "我的收藏", mode: .basic) + } } - +// //var index2: Array> = [] // //class CollectionViewController: UIViewController, UIContextMenuInteractionDelegate { @@ -26,7 +30,7 @@ class CollectionViewController: UIViewController { // let previewControllerInstance = UIViewController() // if identifier < 7 { // let image = UIImageView(frame: CGRect(x: Spaced.screenAuto(), y: Spaced.screenAuto(), width: previewControllerInstance.view.bounds.width - Spaced.screenAuto() * 2, height: previewControllerInstance.view.bounds.width - Spaced.screenAuto() * 2)) -// image.layer.cornerRadius = basicCornerRadius(image.frame.size) * 0.5 +// image.layer.cornerRadius = 15 // image.clipsToBounds = true // image.image = UIImage(named: index2[identifier]["imageName"]!) // previewControllerInstance.view.addSubview(image) @@ -42,7 +46,7 @@ class CollectionViewController: UIViewController { // // 设置精选课程的作者名 // let courseLabel2 = UILabel(frame: CGRect(x: Spaced.screenAuto(), y: courseLabel.frame.maxY + Spaced.control(), width: 0, height: 0)) // courseLabel2.text = index2[identifier]["author"] -// courseLabel2.font = UIFont.systemFont(ofSize: CGFloat(titleFont3), weight: .regular) +// courseLabel2.font = Font.title3() // courseLabel2.sizeToFit() // courseLabel2.isUserInteractionEnabled = false // previewControllerInstance.view.addSubview(courseLabel2) @@ -50,7 +54,7 @@ class CollectionViewController: UIViewController { // previewControllerInstance.preferredContentSize = CGSize(width: previewControllerInstance.view.bounds.width, height: courseLabel2.frame.maxY + Spaced.screenAuto()) // } else { // let image = UIImageView(frame: CGRect(x: Spaced.screenAuto(), y: Spaced.screenAuto(), width: previewControllerInstance.view.bounds.width - Spaced.screenAuto() * 2, height: previewControllerInstance.view.bounds.width - Spaced.screenAuto() * 2)) -// image.layer.cornerRadius = basicCornerRadius(image.frame.size) * 0.5 +// image.layer.cornerRadius = 20 // image.clipsToBounds = true // image.image = UIImage(named: index2[identifier - 7]["name"]!) // previewControllerInstance.view.addSubview(image) @@ -58,7 +62,7 @@ class CollectionViewController: UIViewController { // // 设置精选课程的标题 // let courseLabel = UILabel(frame: CGRect(x: Spaced.screenAuto(), y: image.frame.maxY + Spaced.screenAuto(), width: 0, height: 0)) // courseLabel.text = index2[identifier - 7]["name"] -// courseLabel.font = titleFont2 +// courseLabel.font = Font.title2() // courseLabel.sizeToFit() // courseLabel.isUserInteractionEnabled = false // previewControllerInstance.view.addSubview(courseLabel) @@ -66,7 +70,7 @@ class CollectionViewController: UIViewController { // // 设置精选课程的作者名 // let courseLabel2 = UILabel(frame: CGRect(x: Spaced.screenAuto(), y: courseLabel.frame.maxY + Spaced.control(), width: 0, height: 0)) // courseLabel2.text = index2[identifier - 7]["author"] -// courseLabel2.font = UIFont.systemFont(ofSize: CGFloat(titleFont3), weight: .regular) +// courseLabel2.font = Font.title3() // courseLabel2.sizeToFit() // courseLabel2.isUserInteractionEnabled = false // previewControllerInstance.view.addSubview(courseLabel2) @@ -109,18 +113,18 @@ class CollectionViewController: UIViewController { // // // Set the UIScrollView at the underlying of the interface // let mainScrollView = UIScrollView(frame: UIScreen.main.bounds) -// mainScrollView.contentSize = CGSize(width: Screen.width, height: screenHeight * 2) +// mainScrollView.contentSize = CGSize(width: Screen.width, height: Screen.height() * 2) // view.addSubview(mainScrollView) // // // Set the UILabel at the featuredCoursesBox tilte -// let featuredCourseLable = UILabel(frame: CGRect(x: Spaced.screenAuto(), y: Spaced.module()2, width: 0, height: 0)) +// let featuredCourseLable = UILabel(frame: CGRect(x: Spaced.screenAuto(), y: Spaced.module(), width: 0, height: 0)) // featuredCourseLable.text = "收藏夹" // featuredCourseLable.font = titleFont2 // featuredCourseLable.sizeToFit() // mainScrollView.addSubview(featuredCourseLable) // // // Set a UIScrollView of featuredCourses at the top of the interface -// let headerScrollView = UIScrollView(frame: CGRect(x: 0, y: featuredCourseLable.frame.maxY + Spaced.control(), width: Screen.width, height: largeControlSize.height)) +// let headerScrollView = UIScrollView(frame: CGRect(x: 0, y: featuredCourseLable.frame.maxY + Spaced.control(), width: Screen.width(), height: largeControlSize.height)) // headerScrollView.contentSize = CGSize(width: largeControlSize.width * 7 + Spaced.control() * 6 + Spaced.screenAuto() * 2, height: largeControlSize.height) // headerScrollView.showsHorizontalScrollIndicator = false // headerScrollView.clipsToBounds = false @@ -129,7 +133,7 @@ class CollectionViewController: UIViewController { // // Set the UILabel at the featuredCoursesBox tilte // let featuredCourseLable1 = UILabel(frame: CGRect(x: Spaced.screenAuto(), y: Spaced.module()2 + headerScrollView.frame.height + Spaced.module() * 2, width: 0, height: 0)) // featuredCourseLable1.text = "收藏的合集" -// featuredCourseLable1.font = titleFont2 +// featuredCourseLable1.font = Font.title2() // featuredCourseLable1.sizeToFit() // mainScrollView.addSubview(featuredCourseLable1) // diff --git a/Fourm/Fourm/ViewController/DiscussViewController.swift b/Fourm/Fourm/ViewController/DiscussViewController.swift index 829b316..a9b4cc5 100644 --- a/Fourm/Fourm/ViewController/DiscussViewController.swift +++ b/Fourm/Fourm/ViewController/DiscussViewController.swift @@ -2,8 +2,12 @@ //import UIKit import UIKit + class DiscussViewController: UIViewController { - + override func viewDidLoad() { + super.viewDidLoad() + Initialize.view(self, "发现更多", mode: .basic) + } } // //class DiscussViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { diff --git a/Fourm/Fourm/ViewController/LearningViewController.swift b/Fourm/Fourm/ViewController/LearningViewController.swift index 6584695..6b472e2 100644 --- a/Fourm/Fourm/ViewController/LearningViewController.swift +++ b/Fourm/Fourm/ViewController/LearningViewController.swift @@ -2,8 +2,11 @@ import UIKit class LearningViewController: UIViewController { - var featuredCollectionsRandomDataArray: Array> = [] // 接收精选课程的随机数据 + // 发送精选课程的随机数据(废弃⚠️) + var featuredCollectionsRandomDataArray = arrayRandom(number: 7, array: featuredCollectionsDataArray) as! Array> + let underlyView = UIScrollView() + override func viewDidLoad() { super.viewDidLoad() Initialize.view(self, "推荐内容", mode: .basic) @@ -17,9 +20,6 @@ class LearningViewController: UIViewController { underlyView.addSubview(moduleTitle1) // 关联跳转方法 moduleTitle1.addTarget(self, action: #selector(clickModuleTitleControl), for: .touchUpInside) - - // 发送精选课程的随机数据(废弃⚠️) - featuredCollectionsRandomDataArray = arrayRandom(number: 7, array: featuredCollectionsDataArray) as! Array> // 设置第一个模块的横向滚动视图,用来承载第一个模块“精选合集”(待修改⚠️) let moduleView = UIScrollView(frame: CGRect(x: 0, y: moduleTitle1.frame.maxY + Spaced.control(), width: Screen.width(), height: largeControlSize.height)) @@ -40,7 +40,7 @@ class LearningViewController: UIViewController { } /// 模块标题:精选文章 - let moduleTitle2 = UIButton().moduleTitleMode("精选合集", originY: moduleView.frame.maxY + Spaced.module(), mode: .arrow) + let moduleTitle2 = UIButton().moduleTitleMode("精选文章", originY: moduleView.frame.maxY + Spaced.module(), mode: .arrow) underlyView.addSubview(moduleTitle2) // 关联跳转方法 moduleTitle2.addTarget(self, action: #selector(clickModuleTitleControl), for: .touchUpInside) @@ -109,33 +109,37 @@ class LearningViewController: UIViewController { // 记录当前滚动视图的偏移量 var offset: CGPoint? for subview in view.subviews { - if let underlyScrollView = subview as? UIScrollView { - offset = underlyScrollView.contentOffset + if let scrollView = subview as? UIScrollView { + offset = scrollView.contentOffset break } } + + // 屏幕旋转中触发的方法 + coordinator.animate { [self] _ in // 先进行一遍重新绘制充当过渡动画 + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } completion: { [self] _ in + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } + } + + func transitionAnimate(_ offset: CGPoint) { + // 移除旧的滚动视图 + for subview in self.underlyView.subviews { + subview.removeFromSuperview() + } + + // 重新构建界面 + viewDidLoad() - // 在屏幕旋转完成后刷新界面 - coordinator.animate(alongsideTransition: nil) { _ in - // 移除旧的滚动视图 - for subview in self.underlyView.subviews { - subview.removeFromSuperview() - } - - // 重新构建界面 - self.viewDidLoad() - - // 将新的滚动视图的偏移量设置为之前记录的值 - if let offset = offset { - var newOffset = offset - if offset.y < -44 { - newOffset.y = -(self.navigationController?.navigationBar.frame.height)! - } else if offset.y == -44 { - newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) - } - self.underlyView.setContentOffset(newOffset, animated: false) - } + // 将新的滚动视图的偏移量设置为之前记录的值 + var newOffset = offset + if offset.y < -44 { + newOffset.y = -(self.navigationController?.navigationBar.frame.height)! + } else if offset.y == -44 { + newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) } + self.underlyView.setContentOffset(newOffset, animated: false) } } diff --git a/Fourm/Fourm/ViewController/SearchViewController.swift b/Fourm/Fourm/ViewController/SearchViewController.swift index f99e55e..7cc9682 100644 --- a/Fourm/Fourm/ViewController/SearchViewController.swift +++ b/Fourm/Fourm/ViewController/SearchViewController.swift @@ -16,7 +16,7 @@ class SearchViewController: UIViewController { super.viewDidLoad() Initialize.view(self, "搜索与设置", mode: .group) - // 添加底层试图 + // 添加底层视图 underlyView.frame = Screen.bounds() view.addSubview(underlyView) @@ -197,32 +197,36 @@ extension SearchViewController { // 记录当前滚动视图的偏移量 var offset: CGPoint? for subview in view.subviews { - if let scroll = subview as? UIScrollView { - offset = scroll.contentOffset + if let scrollView = subview as? UIScrollView { + offset = scrollView.contentOffset break } } + + // 屏幕旋转中触发的方法 + coordinator.animate { [self] _ in // 先进行一遍重新绘制充当过渡动画 + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } completion: { [self] _ in + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } + } + + func transitionAnimate(_ offset: CGPoint) { + // 移除旧的滚动视图 + for subview in self.underlyView.subviews { + subview.removeFromSuperview() + } + + // 重新构建界面 + viewDidLoad() - // 在屏幕旋转完成后刷新界面 - coordinator.animate(alongsideTransition: nil) { _ in - // 移除旧的滚动视图 - for subview in self.underlyView.subviews { - subview.removeFromSuperview() - } - - // 重新构建界面 - self.viewDidLoad() - - // 将新的滚动视图的偏移量设置为之前记录的值 - if let offset = offset { - var newOffset = offset - if offset.y < -44 { - newOffset.y = -(self.navigationController?.navigationBar.frame.height)! - } else if offset.y == -44 { - newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) - } - self.underlyView.setContentOffset(newOffset, animated: false) - } + // 将新的滚动视图的偏移量设置为之前记录的值 + var newOffset = offset + if offset.y < -44 { + newOffset.y = -(self.navigationController?.navigationBar.frame.height)! + } else if offset.y == -44 { + newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) } + self.underlyView.setContentOffset(newOffset, animated: false) } } diff --git a/Fourm/Fourm/ViewController/SecondViewController/EssayViewController.swift b/Fourm/Fourm/ViewController/SecondViewController/EssayViewController.swift index beb1a05..6abfeb4 100644 --- a/Fourm/Fourm/ViewController/SecondViewController/EssayViewController.swift +++ b/Fourm/Fourm/ViewController/SecondViewController/EssayViewController.swift @@ -28,35 +28,38 @@ class EssayViewController: UIViewController { break } } - - // 在屏幕旋转完成后刷新界面 - coordinator.animate(alongsideTransition: nil) { _ in - // 移除旧的滚动视图 - for subview in self.view.subviews { - if subview is UIScrollView { - subview.removeFromSuperview() - } + + // 屏幕旋转中触发的方法 + coordinator.animate { [self] _ in // 先进行一遍重新绘制充当过渡动画 + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } completion: { [self] _ in + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } + } + + func transitionAnimate(_ offset: CGPoint) { + // 移除旧的滚动视图 + for subview in self.view.subviews { + if subview is UIScrollView { + subview.removeFromSuperview() } + } + + // 重新构建界面 + let fileURL = Bundle.main.path(forResource: "File", ofType: "") + let content = try! String(contentsOfFile: fileURL!, encoding: .utf8) + let scrollView = essayInterfaceBuild(content, self) - // 重新构建界面 - let fileURL = Bundle.main.path(forResource: "File", ofType: "") - let content = try! String(contentsOfFile: fileURL!, encoding: .utf8) - let scrollView = essayInterfaceBuild(content, self) - - // 将新的滚动视图的偏移量设置为之前记录的值 - if let offset = offset { - var newOffset = offset - if offset.y < -44 { - newOffset.y = -(self.navigationController?.navigationBar.frame.height)! - } else if offset.y == -44 { - newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) - } - scrollView.setContentOffset(newOffset, animated: false) - } + // 将新的滚动视图的偏移量设置为之前记录的值 + var newOffset = offset + if offset.y < -44 { + newOffset.y = -(self.navigationController?.navigationBar.frame.height)! + } else if offset.y == -44 { + newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) } + scrollView.setContentOffset(newOffset, animated: false) } - // 实现观察者方法 @objc func themeDidChange() { // 更新主题相关的设置 diff --git a/Fourm/Fourm/ViewController/SecondViewController/SettingViewController.swift b/Fourm/Fourm/ViewController/SecondViewController/SettingViewController.swift index b519e6c..fc08c21 100644 --- a/Fourm/Fourm/ViewController/SecondViewController/SettingViewController.swift +++ b/Fourm/Fourm/ViewController/SecondViewController/SettingViewController.swift @@ -5,12 +5,14 @@ class SettingViewController: UIViewController { /// 接收模块`1`控件`1`(偏好设置模块)的主题切换按钮,目的是为了当主题切换后可以定位到具体按钮然后切换复选框 var buttonArray: Array = [] + /// 底层的滚动视图,最基础的界面 + let underlyView = UIScrollView() + override func viewDidLoad() { super.viewDidLoad() Initialize.view(self, "偏好设置", mode: .group) - /// 底层的滚动视图,最基础的界面 - let underlyView = UIScrollView() + // 添加底层视图 underlyView.frame = Screen.bounds() view.addSubview(underlyView) @@ -96,8 +98,18 @@ class SettingViewController: UIViewController { (module1Control2Dictionary["label\(i)"] as! UILabel).text = module1Control2LabelArray[i - 1] } + /// 显示与排版(模块`1`)的设置控件`3`(对应的字典) + let module1Control3Dictionary = Setting.controlBuild(caption: "界面显示方向设置", control: [.toggle, .forward], tips: "标准模式下阅读界面的方向跟随系统方向,其余界面保持竖向。") + module1Control3Dictionary["view"]!.frame.origin = CGPoint(x: Spaced.screenAuto(), y: module1Control2Dictionary["view"]!.frame.maxY + Spaced.setting()) + underlyView.addSubview(module1Control3Dictionary["view"]!) + // 配置每一行的左侧文本内容 + let module1Control3LabelArray = ["标准模式", "更多显示方向设置"] + for i in 1 ... module1Control3LabelArray.count { + (module1Control3Dictionary["label\(i)"] as! UILabel).text = module1Control3LabelArray[i - 1] + } + /// 模块标题`2`:通知与推荐 - let moduleTitle2 = UIButton().moduleTitleMode("通知与推送", originY: module1Control2Dictionary["view"]!.frame.maxY + Spaced.module(), mode: .basic) + let moduleTitle2 = UIButton().moduleTitleMode("通知与推送", originY: module1Control3Dictionary["view"]!.frame.maxY + Spaced.module(), mode: .basic) underlyView.addSubview(moduleTitle2) /// 通知与推送(模块`2`)的设置控件`1`(对应的字典) @@ -161,3 +173,46 @@ extension SettingViewController { NotificationCenter.default.post(name: changeThemeNotification, object: nil) } } + +// 扩展,放置界面显示效果修改后执行的所有方法 +extension SettingViewController { + /// 当屏幕旋转时触发的方法 + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + // 记录当前滚动视图的偏移量 + var offset: CGPoint? + for subview in view.subviews { + if let scrollView = subview as? UIScrollView { + offset = scrollView.contentOffset + break + } + } + + // 屏幕旋转中触发的方法 + coordinator.animate { [self] _ in // 先进行一遍重新绘制充当过渡动画 + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } completion: { [self] _ in + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } + } + + func transitionAnimate(_ offset: CGPoint) { + // 移除旧的滚动视图 + for subview in self.underlyView.subviews { + subview.removeFromSuperview() + } + + // 重新构建界面 + viewDidLoad() + + // 将新的滚动视图的偏移量设置为之前记录的值 + var newOffset = offset + if offset.y < -44 { + newOffset.y = -(self.navigationController?.navigationBar.frame.height)! + } else if offset.y == -44 { + newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) + } + self.underlyView.setContentOffset(newOffset, animated: false) + } +} diff --git a/Fourm/Fourm/ViewController/SettingViewController/EssayThemeViewController.swift b/Fourm/Fourm/ViewController/SettingViewController/EssayThemeViewController.swift index 808058f..c4e27d4 100644 --- a/Fourm/Fourm/ViewController/SettingViewController/EssayThemeViewController.swift +++ b/Fourm/Fourm/ViewController/SettingViewController/EssayThemeViewController.swift @@ -8,13 +8,15 @@ import UIKit class EssayThemeViewController: UIViewController { + + /// 底层的滚动视图,最基础的界面 + let underlyView = UIScrollView() override func viewDidLoad() { super.viewDidLoad() Initialize.view(self, "高级阅读设置", mode: .group) - /// 底层的滚动视图,最基础的界面 - let underlyView = UIScrollView() + // 添加底层视图 underlyView.frame = Screen.bounds() view.addSubview(underlyView) @@ -40,8 +42,20 @@ class EssayThemeViewController: UIViewController { } // 配置每一行关联的方法 (module1Control1Dictionary["control1"] as! UISwitch).isOn = (UserDefaults.SettingInfo.string(forKey: .essayCodeNumber)! == "true") ? true: false - - (module1Control1Dictionary["control1"] as! UISwitch).addTarget(self, action: #selector(EssayThemeViewController.module1Control1Row1Switch), for: .valueChanged) + (module1Control1Dictionary["control1"] as! UISwitch).addTarget(self, action: #selector(module1Control1Row1Switch), for: .valueChanged) + + /// 代码块(模块`1`)的设置控件`2`(对应的字典) + let module1Control2Dictionary = Setting.controlBuild(control: [.toggle, .toggle, .forward]) + module1Control2Dictionary["view"]!.frame.origin = CGPoint(x: Spaced.screenAuto(), y: module1Control1Dictionary["view"]!.frame.maxY + Spaced.setting()) + underlyView.addSubview(module1Control2Dictionary["view"]!) + // 配置每一行的左侧文本内容 + let module1Control2LabelArray = ["去除前后空行", "语法高亮", "自定义高亮"] + for i in 1 ... module1Control2LabelArray.count { + (module1Control2Dictionary["label\(i)"] as! UILabel).text = module1Control2LabelArray[i - 1] + } + // 配置每一行关联的方法 + (module1Control2Dictionary["control1"] as! UISwitch).isOn = (UserDefaults.SettingInfo.string(forKey: .essayCodeFristAndList)! == "true") ? true: false + (module1Control2Dictionary["control1"] as! UISwitch).addTarget(self, action: #selector(module1Control2Row1Switch), for: .valueChanged) } } @@ -52,7 +66,60 @@ extension EssayThemeViewController { } else { UserDefaults.SettingInfo.set(value: "false", forKey: .essayCodeNumber) } - // 在需要切换主题的地方发送通知 + // 切换主题相关设置,发送通知 + NotificationCenter.default.post(name: changeThemeNotification, object: nil) + } + @objc func module1Control2Row1Switch(sender: UISwitch) { + if sender.isOn { + UserDefaults.SettingInfo.set(value: "true", forKey: .essayCodeFristAndList) + } else { + UserDefaults.SettingInfo.set(value: "false", forKey: .essayCodeFristAndList) + } + // 切换主题相关设置,发送通知 NotificationCenter.default.post(name: changeThemeNotification, object: nil) } } + +// 扩展,放置界面显示效果修改后执行的所有方法 +extension EssayThemeViewController { + /// 当屏幕旋转时触发的方法 + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + // 记录当前滚动视图的偏移量 + var offset: CGPoint? + for subview in view.subviews { + if let scrollView = subview as? UIScrollView { + offset = scrollView.contentOffset + break + } + } + + // 屏幕旋转中触发的方法 + coordinator.animate { [self] _ in // 先进行一遍重新绘制充当过渡动画 + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } completion: { [self] _ in + transitionAnimate(offset ?? CGPoint(x: 0, y: 0)) + } + } + + func transitionAnimate(_ offset: CGPoint) { + // 移除旧的滚动视图 + for subview in self.underlyView.subviews { + subview.removeFromSuperview() + } + + // 重新构建界面 + viewDidLoad() + + // 将新的滚动视图的偏移量设置为之前记录的值 + var newOffset = offset + if offset.y < -44 { + newOffset.y = -(self.navigationController?.navigationBar.frame.height)! + } else if offset.y == -44 { + newOffset.y = -((self.navigationController?.navigationBar.frame.height)! + Screen.safeAreaInsets().top) + } + self.underlyView.setContentOffset(newOffset, animated: false) + } +} +