├── .DS_Store
├── Demo
├── .DS_Store
├── MultilevelMenuOC
│ ├── .DS_Store
│ ├── MultilevelMenuOC
│ │ ├── Assets.xcassets
│ │ │ ├── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── .DS_Store
│ │ ├── ViewController.h
│ │ ├── AppDelegate.h
│ │ ├── main.m
│ │ ├── Info.plist
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── AppDelegate.m
│ │ └── ViewController.m
│ ├── MultilevelMenuOC.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── project.pbxproj
│ ├── MultilevelMenuOCTests
│ │ ├── Info.plist
│ │ └── MultilevelMenuOCTests.m
│ └── MultilevelMenuOCUITests
│ │ ├── Info.plist
│ │ └── MultilevelMenuOCUITests.m
└── MultilevelMenuSwift
│ ├── .DS_Store
│ ├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── CustomMenu
│ ├── China.png
│ ├── CustomCell.swift
│ ├── CustomMenuView.swift
│ └── CustomCell.xib
│ ├── MultilevelMenu.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
│ ├── Info.plist
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── AppDelegate.swift
│ ├── ViewController.swift
│ └── businessType.json
├── Screenshots
├── MultilevelStyle1Menu.gif
├── MultilevelStyle2Menu.gif
├── MultilevelStyle1Menu_True.gif
├── MultilevelStyle2Menu_True.gif
└── MultilevelStyle2Menu_Custom.gif
├── podfile
├── MultilevelMenu
├── Resources
│ └── MultilevelMenuBundle.bundle
│ │ ├── Info.plist
│ │ ├── btn_common_close_wh.png
│ │ ├── btn_common_close_wh@2x.png
│ │ └── btn_common_close_wh@3x.png
└── Source
│ ├── MenuDataModel.swift
│ ├── MenuMarco.swift
│ ├── MultilevelMenuStyle1View.swift
│ ├── MultilevelMenuStyle2View.swift
│ ├── MultilevelMenuOption.swift
│ ├── MultilevelMenuView.swift
│ ├── MultilevelStlyeMenu.swift
│ ├── MultilevelStyle1Menu.swift
│ └── MultilevelStyle2Menu.swift
├── MultilevelMenu.podspec
├── LICENSE
├── .gitignore
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/.DS_Store
--------------------------------------------------------------------------------
/Demo/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Demo/.DS_Store
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Demo/MultilevelMenuOC/.DS_Store
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Demo/MultilevelMenuSwift/.DS_Store
--------------------------------------------------------------------------------
/Screenshots/MultilevelStyle1Menu.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Screenshots/MultilevelStyle1Menu.gif
--------------------------------------------------------------------------------
/Screenshots/MultilevelStyle2Menu.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Screenshots/MultilevelStyle2Menu.gif
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Screenshots/MultilevelStyle1Menu_True.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Screenshots/MultilevelStyle1Menu_True.gif
--------------------------------------------------------------------------------
/Screenshots/MultilevelStyle2Menu_True.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Screenshots/MultilevelStyle2Menu_True.gif
--------------------------------------------------------------------------------
/Screenshots/MultilevelStyle2Menu_Custom.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Screenshots/MultilevelStyle2Menu_Custom.gif
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/CustomMenu/China.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Demo/MultilevelMenuSwift/CustomMenu/China.png
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/Demo/MultilevelMenuOC/MultilevelMenuOC/.DS_Store
--------------------------------------------------------------------------------
/podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 | platform :ios,'8.0'
3 | use_frameworks!
4 |
5 | target 'MultilevelMenu' do
6 | pod 'MultilevelMenu'
7 | end
8 |
--------------------------------------------------------------------------------
/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/Info.plist:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/Info.plist
--------------------------------------------------------------------------------
/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/btn_common_close_wh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/btn_common_close_wh.png
--------------------------------------------------------------------------------
/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/btn_common_close_wh@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/btn_common_close_wh@2x.png
--------------------------------------------------------------------------------
/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/btn_common_close_wh@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChokShen/MultilevelMenu/HEAD/MultilevelMenu/Resources/MultilevelMenuBundle.bundle/btn_common_close_wh@3x.png
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/MultilevelMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // MultilevelMenuOC
4 | //
5 | // Created by forwor on 2019/8/9.
6 | // Copyright © 2019 forwor. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 | @end
13 |
14 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/MultilevelMenu.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // MultilevelMenuOC
4 | //
5 | // Created by forwor on 2019/8/9.
6 | // Copyright © 2019 forwor. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // MultilevelMenuOC
4 | //
5 | // Created by forwor on 2019/8/9.
6 | // Copyright © 2019 forwor. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MultilevelMenu.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "MultilevelMenu"
3 | s.version = "1.3.2"
4 | s.summary = "MultilevelMenu"
5 | s.description = "A custom multi-level menu/ address picker"
6 | s.homepage = "https://github.com/ChokShen/MultilevelMenu"
7 | s.license = { :type => "MIT", :file => "LICENSE" }
8 | s.author = { "shenzhiqiang" => "295297647@qq.com" }
9 | s.ios.deployment_target = '8.0'
10 | s.source = { :git => "https://github.com/ChokShen/MultilevelMenu.git", :tag => "1.3.2" }
11 | s.source_files = "MultilevelMenu/Source/**/*.swift"
12 | s.resources = "MultilevelMenu/Resources/MultilevelMenuBundle.bundle"
13 | s.framework = 'Foundation', 'UIKit'
14 | s.requires_arc = true
15 | s.swift_version = '5.0'
16 | end
17 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOCTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOCUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/CustomMenu/CustomCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomCell.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by shenzhiqiang on 2018/5/7.
6 | // Copyright © 2018年 ChokShen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CustomCell: UITableViewCell {
12 |
13 | @IBOutlet weak var contenLabel: UILabel!
14 | @IBOutlet weak var seperator: UILabel! {
15 | didSet {
16 | seperator.backgroundColor = UIColor.white
17 | }
18 | }
19 |
20 | @IBOutlet weak var iconImageView: UIImageView!
21 | override func awakeFromNib() {
22 | super.awakeFromNib()
23 | // Initialization code
24 | }
25 |
26 | override func setSelected(_ selected: Bool, animated: Bool) {
27 | super.setSelected(selected, animated: animated)
28 |
29 | // Configure the view for the selected state
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MenuDataModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MenuDataModel.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/4/27.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class MenuDataModel: NSObject {
12 | ///Id of a piece of data in menu,required
13 | @objc open var id: String?
14 | ///Data name,required
15 | @objc open var name: String?
16 | ///Data value,optional
17 | @objc open var value: String?
18 | ///Id of last-level menu,required
19 | @objc open var pid: String?
20 | ///Menu current level,optional
21 | open var level: Int?
22 |
23 | public override init() {}
24 |
25 | @objc public init(dict: [AnyHashable: Any]) {
26 | self.id = dict["id"] as? String
27 | self.name = dict["name"] as? String
28 | self.value = dict["value"] as? String
29 | self.pid = dict["pid"] as? String
30 | self.level = dict["level"] as? Int
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOCTests/MultilevelMenuOCTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelMenuOCTests.m
3 | // MultilevelMenuOCTests
4 | //
5 | // Created by forwor on 2019/8/9.
6 | // Copyright © 2019 forwor. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MultilevelMenuOCTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation MultilevelMenuOCTests
16 |
17 | - (void)setUp {
18 | // Put setup code here. This method is called before the invocation of each test method in the class.
19 | }
20 |
21 | - (void)tearDown {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | - (void)testExample {
26 | // This is an example of a functional test case.
27 | // Use XCTAssert and related functions to verify your tests produce the correct results.
28 | }
29 |
30 | - (void)testPerformanceExample {
31 | // This is an example of a performance test case.
32 | [self measureBlock:^{
33 | // Put the code you want to measure the time of here.
34 | }];
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 ChokShen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/CustomMenu/CustomMenuView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomMenuView.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by shenzhiqiang on 2018/5/7.
6 | // Copyright © 2018年 ChokShen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CustomMenuView: MultilevelMenuStyle2View {
12 |
13 | // MARK: - UITableViewDelegate
14 | open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
15 | var cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as? CustomCell
16 | if cell == nil {
17 | cell = Bundle.main.loadNibNamed("CustomCell", owner: nil, options: nil)?.first as? CustomCell
18 | }
19 | cell?.contenLabel?.text = dataSouce[indexPath.row].name //Text
20 | //cell?.iconImageView.image = UIImage(named: dataSouce[indexPath.row].value!) //Image
21 | cell?.tintColor = option.checkMarkColor
22 | if indexPath == lastSelectedIndexPath {
23 | cell?.accessoryType = .checkmark
24 | } else {
25 | cell?.accessoryType = .none
26 | }
27 | return cell!
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOCUITests/MultilevelMenuOCUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelMenuOCUITests.m
3 | // MultilevelMenuOCUITests
4 | //
5 | // Created by forwor on 2019/8/9.
6 | // Copyright © 2019 forwor. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MultilevelMenuOCUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation MultilevelMenuOCUITests
16 |
17 | - (void)setUp {
18 | // Put setup code here. This method is called before the invocation of each test method in the class.
19 |
20 | // In UI tests it is usually best to stop immediately when a failure occurs.
21 | self.continueAfterFailure = NO;
22 |
23 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
24 | [[[XCUIApplication alloc] init] launch];
25 |
26 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
27 | }
28 |
29 | - (void)tearDown {
30 | // Put teardown code here. This method is called after the invocation of each test method in the class.
31 | }
32 |
33 | - (void)testExample {
34 | // Use recording to get started writing UI tests.
35 | // Use XCTAssert and related functions to verify your tests produce the correct results.
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MenuMarco.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelMenuVariable.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/5/10.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | struct MMScreen {
13 | ///屏幕宽度
14 | static let width = UIScreen.main.bounds.width
15 | ///屏幕高度
16 | static let height = UIScreen.main.bounds.height
17 | ///状态栏的高度
18 | static let statusBarHeight = UIApplication.shared.statusBarFrame.height
19 | ///导航栏的高度
20 | static let navigationBarHeight: CGFloat = 44
21 | ///状态栏+导航栏的高度
22 | static let navigationHeight = statusBarHeight + navigationBarHeight
23 | ///底部安全距离
24 | static let bottomSafeHeight: CGFloat = isFullScreen ? 34 : 0
25 | ///是否全面屏
26 | static var isFullScreen: Bool {
27 | if #available(iOS 11, *) {
28 | guard let w = UIApplication.shared.delegate?.window, let unwrapedWindow = w else {
29 | return false
30 | }
31 |
32 | if unwrapedWindow.safeAreaInsets.bottom > 0 {
33 | print(unwrapedWindow.safeAreaInsets)
34 | return true
35 | }
36 | }
37 | return false
38 | }
39 |
40 | }
41 |
42 | ///动画完成的代码块
43 | public typealias AnimationCompletionClosure = (Bool) -> Void
44 | ///点击辅助按钮的代码块
45 | public typealias ClickSupplementaryButtonClosure = (Int) -> Void
46 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | .build/
41 |
42 | # CocoaPods
43 | #
44 | # We recommend against adding the Pods directory to your .gitignore. However
45 | # you should judge for yourself, the pros and cons are mentioned at:
46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47 | #
48 | # Pods/
49 |
50 | # Carthage
51 | #
52 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
53 | # Carthage/Checkouts
54 |
55 | Carthage/Build
56 |
57 | # fastlane
58 | #
59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60 | # screenshots whenever they are needed.
61 | # For more information about the recommended setup visit:
62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
63 |
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MultilevelMenuStyle1View.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PickerListView.swift
3 | // FWOMSMerchant
4 | //
5 | // Created by ChokShen on 2018/5/10.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol MultilevelMenuStlye1ViewDelegate: class {
12 | func didSelectRow(_ listView: MultilevelMenuStyle1View, _ row: Int, _ dateModel: MenuDataModel)
13 | }
14 |
15 | open class MultilevelMenuStyle1View: MultilevelMenuView {
16 |
17 | weak var delegate: MultilevelMenuStlye1ViewDelegate?
18 |
19 | //MARK: - Animation
20 | override func popFromRightAnimation(_ completion: AnimationCompletionClosure? = nil) {
21 | UIView.animate(withDuration: 0.5, animations: {
22 | self.animationView.frame.origin.x = 0
23 | }) { (finished) in
24 | if finished {
25 | self.animationView.frame.size = CGSize(width: self.initialWidth, height: self.bounds.height)
26 | self.tableView.frame.size = CGSize(width: self.animationView.bounds.width, height: self.tableView.bounds.height)
27 | }
28 | }
29 | }
30 |
31 | override func hideAnimation(_ completion: AnimationCompletionClosure? = nil) {
32 | UIView.animate(withDuration: 0.5, animations: {
33 | self.animationView.frame.origin.x = MMScreen.width
34 | }) { (finished) in
35 | if finished {
36 | self.removeFromSuperview()
37 | if completion != nil {
38 | completion!(finished)
39 | }
40 | }
41 | }
42 | }
43 |
44 | // MARK: - UITableViewDelegate & UITableViewDataSource
45 | open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
46 | super.tableView(tableView, didSelectRowAt: indexPath)
47 | delegate?.didSelectRow(self, indexPath.row, dataSouce[indexPath.row])
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // MultilevelMenuOC
4 | //
5 | // Created by forwor on 2019/8/9.
6 | // Copyright © 2019 forwor. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // MultilevelMenuOC
4 | //
5 | // Created by forwor on 2019/8/9.
6 | // Copyright © 2019 forwor. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "MultilevelMenuOC-Swift.h"
11 |
12 | @interface ViewController ()
13 | @property (weak, nonatomic) IBOutlet UILabel *resultLabel;
14 | @end
15 |
16 | @implementation ViewController
17 |
18 | - (void)viewDidLoad {
19 | [super viewDidLoad];
20 | // Do any additional setup after loading the view, typically from a nib.
21 | }
22 |
23 | - (IBAction)testAction:(id)sender {
24 | NSMutableArray *dataSource = [NSMutableArray array];
25 | NSString *path = [[NSBundle mainBundle] pathForResource:@"businessType" ofType:@"json"];
26 | NSData *data = [NSData dataWithContentsOfFile:path];
27 | NSArray *tempArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:NULL];
28 | for (NSDictionary *dic in tempArray) {
29 | //将字典数组转换成模型数组
30 | MenuDataModel *model = [[MenuDataModel alloc] initWithDict:dic];
31 | //将模型存入到属性中
32 | [dataSource addObject:model];
33 | }
34 |
35 | __weak typeof(self) weakSelf = self;
36 | MultilevelStyle1Menu *menu = [[MultilevelStyle1Menu alloc]initWithTitle:@"行业类型" dataSouce:dataSource option:nil customView:nil completion:^(NSString * text, MenuDataModel * model) {
37 | weakSelf.resultLabel.text = text;
38 | }];
39 | [menu show];
40 | }
41 |
42 | - (IBAction)customMenu:(id)sender {
43 | NSString *path = [[NSBundle mainBundle] pathForResource:@"businessType" ofType:@"json"];
44 | NSURL *url = [NSURL fileURLWithPath:path];
45 | MultilevelMenuOption *option = [[MultilevelMenuOption alloc]init];
46 | option.rightBarButtonTitle = @"ok";
47 | option.rightBarButtonColor = [UIColor redColor];
48 | __weak typeof(self) weakSelf = self;
49 | MultilevelStyle2Menu *menu = [[MultilevelStyle2Menu alloc] initWithTitle:@"请选择行业类型" fileUrl:url option:option customView:nil completion:^(NSString * text, MenuDataModel * model) {
50 | weakSelf.resultLabel.text = text;
51 | }];
52 | [menu show];
53 |
54 | }
55 |
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/4/27.
6 | // Copyright © 2018年 ChokShen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/4/27.
6 | // Copyright © 2018年 ChokShen. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | private var customView: MultilevelMenuStyle1View!
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 | // // Do any additional setup after loading the view, typically from a nib.
18 | }
19 |
20 | func getClassName(_ view: MultilevelMenuStyle1View) -> String {
21 | return String(describing: type(of: view))
22 | }
23 |
24 | @IBOutlet weak var resultLabel: UILabel!
25 | @IBAction func testAction(_ sender: Any) {
26 | var dataSouce: [MenuDataModel] = []
27 | guard let path = Bundle.main.path(forResource:"businessType", ofType: "json") else { return }
28 | let url = URL(fileURLWithPath: path)
29 | do{
30 | let data = try Data(contentsOf: url)
31 | let json:Any = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.mutableContainers)
32 | if let jsonArray = json as? [[String: String]] {
33 | for dict in jsonArray {
34 | let dataModel = MenuDataModel.init(dict: dict)
35 | dataSouce.append(dataModel)
36 | }
37 | }
38 | }catch{
39 | print("读取本地数据出现错误!",error)
40 | }
41 | let menu = MultilevelStyle1Menu(title: "行业类型", dataSouce: dataSouce, completion: { (resultString, model) in
42 | self.resultLabel.text = resultString
43 | })
44 | //menu.allowSelectAnyLevelData = true
45 | menu.show()
46 | }
47 |
48 | @IBAction func customMenu(_ sender: Any) {
49 | guard let path = Bundle.main.path(forResource:"businessType", ofType: "json") else { return }
50 | let url = URL(fileURLWithPath: path)
51 | let option = MultilevelMenuOption()
52 | option.rightBarButtonTitle = "ok"
53 | option.rightBarButtonColor = UIColor.red
54 | let menu = MultilevelStyle2Menu(title: "请选择行业类型", fileUrl: url, option: option, customView: CustomMenuView(), completion: { (resultString, model) in
55 | self.resultLabel.text = resultString
56 | })
57 | menu.show()
58 | }
59 | override func didReceiveMemoryWarning() {
60 | super.didReceiveMemoryWarning()
61 | // Dispose of any resources that can be recreated.
62 | }
63 |
64 |
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MultilevelMenuStyle2View.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelMenuView.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/4/27.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol MultilevelMenuStlye2ViewDelegate: class {
12 | func didSelectRow(_ menuView: MultilevelMenuStyle2View, _ row: Int, _ dataModel: MenuDataModel)
13 | func didRemoveFromView(_ menuView: MultilevelMenuStyle2View)
14 | }
15 |
16 | open class MultilevelMenuStyle2View: MultilevelMenuView{
17 |
18 | override var initialWidth: CGFloat {
19 | get {
20 | return MMScreen.width - self.option.secondaryMenuWidth
21 | }
22 | }
23 | weak var delegate: MultilevelMenuStlye2ViewDelegate?
24 | private lazy var backgroundView: UIView = {
25 | let backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: self.option.secondaryMenuWidth, height: self.bounds.height))
26 | backgroundView.backgroundColor = UIColor.init(white: 1, alpha: 0)
27 | backgroundView.isUserInteractionEnabled = true
28 | backgroundView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.hideAnimation_ClickBackgroundView)))
29 | return backgroundView
30 | }()
31 |
32 | //MARK: - Animation
33 | override func popFromRightAnimation(_ completion: AnimationCompletionClosure? = nil) {
34 | UIView.animate(withDuration: 0.5, animations: {
35 | self.animationView.frame.origin.x = self.option.secondaryMenuWidth
36 | }) { (finished) in
37 | if finished {
38 | self.animationView.frame.size = CGSize(width: self.initialWidth, height: self.bounds.height)
39 | self.tableView.frame.size = CGSize(width: self.animationView.bounds.width, height: self.tableView.bounds.height)
40 | self.addSubview(self.backgroundView)
41 | }
42 | }
43 | }
44 |
45 | @objc func hideAnimation_ClickBackgroundView() {
46 | UIView.animate(withDuration: 0.5, animations: {
47 | self.animationView.frame.origin.x = MMScreen.width
48 | }) { (finished) in
49 | if finished {
50 | self.backgroundView.removeFromSuperview()
51 | self.removeFromSuperview()
52 | self.delegate?.didRemoveFromView(self)
53 | }
54 | }
55 | }
56 |
57 | func hideAnimation_ClickButton(_ completion: AnimationCompletionClosure? = nil) {
58 | UIView.animate(withDuration: 0.5, animations: {
59 | self.animationView.frame.origin.x = MMScreen.width
60 | }) { (finished) in
61 | if finished {
62 | self.backgroundView.removeFromSuperview()
63 | self.removeFromSuperview()
64 | if completion != nil {
65 | completion!(finished)
66 | }
67 | }
68 | }
69 | }
70 |
71 | func fullAnimation() {
72 | UIView.animate(withDuration: 0.5, animations: {
73 | self.animationView.frame.origin.x = 0
74 | }) { (finished) in
75 | if finished {
76 | self.animationView.frame.size = CGSize(width: MMScreen.width, height: self.bounds.height)
77 | self.tableView.frame.size = CGSize(width: self.animationView.bounds.width, height: self.tableView.bounds.height)
78 | }
79 | }
80 | }
81 |
82 | open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
83 | super.tableView(tableView, didSelectRowAt: indexPath)
84 | delegate?.didSelectRow(self, indexPath.row, dataSouce[indexPath.row])
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MultilevelMenuOption.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelMenuOption.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/4/27.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | public class MultilevelMenuOption: NSObject {
13 |
14 | //MARK: - Common Option
15 | ///文本的字体
16 | @objc public var textFont: UIFont = UIFont.systemFont(ofSize: 17)
17 | ///文本的颜色
18 | @objc public var textColor: UIColor = UIColor.black
19 | ///勾选的颜色
20 | @objc public var checkMarkColor: UIColor = UIColor.material_cyan_accent_normal
21 | ///顶部视图左边文字颜色
22 | @objc public var upperBarLeftTextColor: UIColor = UIColor.ColorFromRGB(rgbValue: 0x999999)
23 | ///顶部视图左边文字字体
24 | @objc public var upperBarLeftTextFont: UIFont = UIFont.boldSystemFont(ofSize: 16)
25 | ///顶部视图展示按钮的颜色
26 | @objc public var upperBarButtonColor: UIColor = UIColor.material_cyan_accent_normal
27 | ///顶部视图展示按钮的字体
28 | @objc public var upperBarButtonFont: UIFont = UIFont.boldSystemFont(ofSize: 17)
29 |
30 | //MARK: - Style1Menu Option
31 | @objc public var bottomButtonTitle = "确定"
32 | @objc public var bottomButtonBackgroundColor_Normal: UIColor = UIColor.material_cyan_accent_normal
33 | @objc public var bottomButtonBackgroundColor_Disable: UIColor = UIColor.material_cyan_accent_disabled
34 | @objc public var bottomButtonBackgroundColor_Highlighted: UIColor = UIColor.material_cyan_accent_highlighted
35 |
36 | //MARK: - Style2Menu Option
37 | ///次级菜单(级数大于1的菜单)的宽度
38 | @objc public var secondaryMenuWidth: CGFloat = 80
39 | ///自定义导航栏的背景色
40 | @objc public var navigationBarColor: UIColor = UIColor.navigationBarColor
41 | ///导航标题的颜色
42 | @objc public var navigationTitleColor: UIColor = UIColor.black
43 | ///左侧关闭按钮的颜色
44 | @objc public var closeButtonColor: UIColor = UIColor.black
45 | ///右侧导航按钮的标题
46 | @objc public var rightBarButtonTitle: String = "确定"
47 | ///右侧导航按钮的颜色
48 | @objc public var rightBarButtonColor: UIColor = UIColor.black
49 | ///顶部视图左边默认显示的文字
50 | @objc public var upperBarDefalutLeftText = "请选择"
51 | ///选中菜单的一项后顶部视图左边显示的文字
52 | @objc public var upperBarSelectedLeftText = "已选择"
53 |
54 | public override init() {}
55 | }
56 |
57 | //MARK: - Extension
58 | extension UIImage {
59 | //创建有颜色的image
60 | class func imageWithColor(_ color: UIColor) -> UIImage {
61 | let rect = CGRect(x: 0.0, y: 0.0, width: 18.0, height: 18.0)
62 | UIGraphicsBeginImageContext(rect.size)
63 | let context = UIGraphicsGetCurrentContext()
64 |
65 | context?.setFillColor(color.cgColor)
66 | context?.fill(rect)
67 |
68 | let image = UIGraphicsGetImageFromCurrentImageContext()
69 | UIGraphicsEndImageContext()
70 |
71 | return image!
72 | }
73 | }
74 |
75 | extension UIColor {
76 | //RGB颜色
77 | class func ColorFromRGB(rgbValue: UInt) -> UIColor {
78 | return UIColor(red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,blue: CGFloat(rgbValue & 0x0000FF) / 255.0,alpha: CGFloat(1.0)
79 | )
80 | }
81 | class var material_cyan_accent_disabled : UIColor
82 | {
83 | return self.ColorFromRGB(rgbValue: 0x84FFFF )
84 | }
85 |
86 | class var material_cyan_accent_normal : UIColor
87 | {
88 | return self.ColorFromRGB(rgbValue: 0x00E5FF )
89 | }
90 |
91 | class var material_cyan_accent_highlighted : UIColor
92 | {
93 | return self.ColorFromRGB(rgbValue: 0x00B8D4 )
94 | }
95 |
96 | class var protectedBackgroundColor : UIColor
97 | {
98 | return UIColor.init(white: 0.5, alpha: 0.5)
99 | }
100 |
101 | class var navigationBarColor : UIColor
102 | {
103 | return UIColor.init(red: 247/255, green: 247/255, blue: 247/255, alpha: 1)
104 | }
105 |
106 | class var seperatorLineColor : UIColor {
107 | return self.ColorFromRGB(rgbValue: 0xE1E1E1)
108 | }
109 | }
110 |
111 | extension UIImage {
112 | func imageMaskWithColor(_ maskColor: UIColor) -> UIImage {
113 | var newImage:UIImage? = nil
114 | let imageRect = CGRect(origin: CGPoint(x: 0, y: 0), size: self.size)
115 | UIGraphicsBeginImageContextWithOptions(imageRect.size, false, self.scale)
116 | let context = UIGraphicsGetCurrentContext()
117 | context?.scaleBy(x: 1.0, y: -1.0)
118 | context?.translateBy(x: 0.0, y: -(imageRect.size.height))
119 | context?.clip(to: imageRect, mask: self.cgImage!);//选中选区 获取不透明区域路径
120 | context?.setFillColor(maskColor.cgColor);//设置颜色
121 | context?.fill(imageRect);//绘制
122 | newImage = UIGraphicsGetImageFromCurrentImageContext();//提取图片
123 | UIGraphicsEndImageContext()
124 | return newImage!
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MultilevelMenu
2 | A custom multi-level menu/ address picker.
3 | ***
4 | 
5 | ***MultilevelStyle1Menu***
6 |
7 | 
8 | ***MultilevelStyle2Menu***
9 |
10 | ## Requirements
11 | * iOS 8+
12 | * Xcode 11+
13 | * Swift 5.0+
14 |
15 | ## Installation
16 | ### 1.CocoaPods
17 | ```swift
18 | pod 'MultilevelMenu'
19 | ```
20 | ### 2.Manually
21 | Download the project, then drag the files of MultilevelMenu folder to your project.
22 |
23 | ## Basic usage
24 | ### 1.Data structure
25 | ```swift
26 | open class MenuDataModel {
27 | ///Id of a piece of data in menu,required
28 | open var id: String?
29 | ///Data name,required
30 | open var name: String?
31 | ///Data value,optional
32 | open var value: String?
33 | ///Id of last-level menu,required
34 | open var pid: String?
35 | ///Menu current level,optional
36 | open var level: Int?
37 |
38 | public init() {}
39 |
40 | public init(dict: [AnyHashable: Any]) {
41 | self.id = dict["id"] as? String
42 | self.name = dict["name"] as? String
43 | self.value = dict["value"] as? String
44 | self.pid = dict["pid"] as? String
45 | self.level = dict["level"] as? Int
46 | }
47 | }
48 | ```
49 | ### 2.Init
50 |
51 | Data handle
52 | ```swift
53 | let array: [Dictionary] = [
54 | ["id":"01","name":"实物产品行业","value":""],
55 | ["id":"02","name":"服务行业","value":""],
56 | ["id":"0101","name":"综合超市/卖场","pid":"01","value":""],
57 | ["id":"0102","name":"穿戴用品","pid":"01","value":""],
58 | ["id":"0103","name":"饮食产品","pid":"01","value":""],
59 | ["id":"0104","name":"房地产","pid":"01","value":""]
60 | ]
61 |
62 | var dataSouce: [MenuDataModel] = []
63 | for dict in array {
64 | let dataModel = MenuDataModel.init(dict: dict)
65 | dataSouce.append(dataModel)
66 | }
67 | ```
68 | Show
69 | * Swift
70 |
71 | ```swift
72 | let menu = MultilevelStyle1Menu(title: "行业类型", dataSouce: dataSouce, completion: { (resultString, model) in //'resultString' is combined with every level data that you have selected.'model' is the MenuDataModel that you have selected lastly.
73 | self.resultLabel.text = resultString
74 | })
75 | menu.show()
76 | ```
77 | * Objective-C
78 |
79 | ```objective-c
80 | __weak typeof(self) weakSelf = self;
81 | MultilevelStyle1Menu *menu = [[MultilevelStyle1Menu alloc]initWithTitle:@"行业类型" dataSouce:dataSource option:nil customView:nil completion:^(NSString * text, MenuDataModel * model) {
82 | weakSelf.resultLabel.text = text;
83 | }];
84 | [menu show];
85 | ```
86 |
87 | Important Property
88 | ```swfit
89 | menu.allowSelectAnyLevelData = true
90 | // It's false by defalut that it means you must select the last level data, otherwise you can't confirm result.But If it's true, meaning that you can select any level data to confirm result.
91 | ```
92 | 
93 | ***MultilevelStyle1Menu***
94 |
95 | 
96 | ***MultilevelStyle2Menu***
97 |
98 | ## Custom Menu
99 | * Custom Cell
100 | Creat your custom cell by xib or code.
101 | * Create a MultilevelMenuStyle1View or MultilevelMenuStyle2View subclass
102 | ```swift
103 | class CustomMenuView: MultilevelMenuStyle2View {
104 | // MARK: - UITableViewDelegate
105 | open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
106 | var cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as? CustomCell
107 | if cell == nil {
108 | cell = Bundle.main.loadNibNamed("CustomCell", owner: nil, options: nil)?.first as? CustomCell
109 | }
110 | cell?.contenLabel?.text = dataSouce[indexPath.row].name //Text
111 | cell?.iconImageView.image = UIImage(named: dataSouce[indexPath.row].value!) //Image
112 |
113 | //Selected properties
114 | cell?.tintColor = option.checkMarkColor
115 | if indexPath == lastSelectedIndexPath {
116 | cell?.accessoryType = .checkmark
117 | } else {
118 | cell?.accessoryType = .none
119 | }
120 | return cell!
121 | }
122 | }
123 | ```
124 | 
125 |
126 | *Show
127 | * Swift
128 |
129 | ```swift
130 | var option = MultilevelMenuOption()
131 | option.rightBarButtonTitle = "ok"
132 | option.rightBarButtonColor = UIColor.red
133 |
134 | let menu = MultilevelStyle2Menu(title: "请选择行业类型", dataSouce: dataSouce, option: option, customView: CustomMenuView(), completion: { (resultString, model) in
135 | self.resultLabel.text = resultString
136 | })
137 | menu.show()
138 | ```
139 | * Objective-C
140 | ```objective-c
141 | MultilevelMenuOption *option = [[MultilevelMenuOption alloc]init];
142 | option.rightBarButtonTitle = @"ok";
143 | option.rightBarButtonColor = [UIColor redColor];
144 | __weak typeof(self) weakSelf = self;
145 | MultilevelStyle2Menu *menu = [[MultilevelStyle2Menu alloc] initWithTitle:@"请选择行业类型" fileUrl:url option:option customView:nil completion:^(NSString * text, MenuDataModel * model) {
146 | weakSelf.resultLabel.text = text;
147 | }];
148 | [menu show];
149 | ```
150 | You also can creat MultilevelMenuOption to set menu custom properties.
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/CustomMenu/CustomCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MultilevelMenuView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelMenuView.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/5/14.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | open class MultilevelMenuView: UIView, UITableViewDelegate, UITableViewDataSource{
12 |
13 | var isFirst: Bool = false {
14 | didSet {
15 | if isFirst == false {
16 | self.addSubview(animationView)
17 | setUpLayOut()
18 | popFromRightAnimation()
19 | } else {
20 | animationView.frame = self.bounds
21 | self.addSubview(animationView)
22 | setUpLayOut()
23 | }
24 | tableViewConfiguration()
25 | }
26 | }
27 | public var option: MultilevelMenuOption = MultilevelMenuOption()
28 | var initialWidth: CGFloat {
29 | get {
30 | return MMScreen.width
31 | }
32 | }
33 |
34 | public var dataSouce: [MenuDataModel] = [] {
35 | didSet {
36 | tableView.reloadData()
37 | }
38 | }
39 |
40 | lazy var animationView: UIView = {
41 | let animationView = UIView(frame: CGRect(x: MMScreen.width, y: 0, width: self.initialWidth, height: self.bounds.height))
42 | animationView.backgroundColor = UIColor.white
43 | return animationView
44 | }()
45 | lazy var tableView: UITableView = {
46 | let tempTableView = UITableView(frame: CGRect.zero, style: .plain)
47 | return tempTableView
48 | }()
49 | var textLabel: UILabel!
50 | public var lastSelectedIndexPath: IndexPath?
51 |
52 | // MARK: - init
53 | /// 便利初始化方法
54 | ///
55 | /// - Parameters:
56 | /// - frame: 布局
57 | /// - option: 配置参数
58 | /// - isFirst: 是否第一级列表,默认为false
59 | /// - isSupplementaryButton: 是否需要底部辅助按钮,默认为false
60 | convenience init(frame: CGRect, option: MultilevelMenuOption, isFirst: Bool = false) {
61 | self.init(frame: frame)
62 | self.option = option
63 | if isFirst == false {
64 | self.addSubview(animationView)
65 | setUpLayOut()
66 | popFromRightAnimation()
67 | } else {
68 | animationView.frame = self.bounds
69 | self.addSubview(animationView)
70 | setUpLayOut()
71 | }
72 | tableViewConfiguration()
73 | }
74 |
75 | override public init(frame: CGRect) {
76 | super.init(frame: frame)
77 | self.backgroundColor = UIColor.init(white: 0.5, alpha: 0.5)
78 | }
79 |
80 | public init (_ className: String?) {
81 | self.init()
82 | }
83 |
84 | required public init?(coder aDecoder: NSCoder) {
85 | fatalError("init(coder:) has not been implemented")
86 | }
87 |
88 | // MARK: - ui
89 | func setUpLayOut() {
90 | self.tableView.frame = animationView.bounds
91 | animationView.addSubview(self.tableView)
92 | }
93 |
94 | func tableViewConfiguration() {
95 | tableView.delegate = self
96 | tableView.dataSource = self
97 | tableView.separatorStyle = .none
98 | tableView.backgroundColor = UIColor.white
99 | }
100 |
101 | // MARK: - animation
102 | func popFromRightAnimation(_ completion: AnimationCompletionClosure? = nil) {
103 | }
104 |
105 | func hideAnimation(_ completion: AnimationCompletionClosure? = nil) {
106 | UIView.animate(withDuration: 0.5, animations: {
107 | self.animationView.frame.origin.x = MMScreen.width
108 | }) { (finished) in
109 | if finished {
110 | self.removeFromSuperview()
111 | if completion != nil {
112 | completion!(finished)
113 | }
114 | }
115 | }
116 | }
117 |
118 | // MARK: - UITableViewDelegate & UITableViewDataSource
119 | open func numberOfSections(in tableView: UITableView) -> Int {
120 | return 1
121 | }
122 |
123 | open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
124 | return dataSouce.count
125 | }
126 |
127 | open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
128 | var cell = tableView.dequeueReusableCell(withIdentifier: "DisplayedCell")
129 | if cell == nil {
130 | cell = UITableViewCell(style: .default, reuseIdentifier: "DisplayedCell")
131 | }
132 | cell?.textLabel?.text = dataSouce[indexPath.row].name
133 | cell?.textLabel?.textColor = option.textColor
134 | cell?.textLabel?.font = option.textFont
135 | cell?.tintColor = option.checkMarkColor
136 | if indexPath == lastSelectedIndexPath {
137 | cell?.accessoryType = .checkmark
138 | } else {
139 | cell?.accessoryType = .none
140 | }
141 | return cell!
142 | }
143 |
144 | open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
145 | tableView.deselectRow(at: indexPath, animated: true)
146 | let newIndexPath = indexPath
147 | if newIndexPath != lastSelectedIndexPath {
148 | let newCell = tableView.cellForRow(at: newIndexPath)
149 | newCell?.accessoryType = .checkmark
150 | newCell?.tintColor = option.checkMarkColor
151 | if lastSelectedIndexPath != nil {
152 | let lastSelectedCell = tableView.cellForRow(at: lastSelectedIndexPath!)
153 | lastSelectedCell?.accessoryType = .none
154 | }
155 | lastSelectedIndexPath = newIndexPath
156 | }
157 | }
158 |
159 | open func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
160 | return 44
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
31 |
37 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
31 |
37 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/businessType.json:
--------------------------------------------------------------------------------
1 | [{"id":"01","name":"实物产品行业","value":""},{"id":"02","name":"服务行业","value":""},{"id":"0101","name":"综合超市/卖场","pid":"01","value":""},{"id":"0102","name":"穿戴用品","pid":"01","value":""},{"id":"0103","name":"饮食产品","pid":"01","value":""},{"id":"0104","name":"房地产","pid":"01","value":""},{"id":"0105","name":"建材/家居/装饰","pid":"01","value":""},{"id":"0106","name":"日化/日杂用品","pid":"01","value":""},{"id":"0107","name":"办公设备/文娱/体育用品","pid":"01","value":""},{"id":"0108","name":"礼品/婚庆用品","pid":"01","value":""},{"id":"0109","name":"电子产品","pid":"01","value":""},{"id":"0110","name":"出行/旅游相关产品","pid":"01","value":""},{"id":"0111","name":"医药/保健器材及用品","pid":"01","value":""},{"id":"0112","name":"机电设备及产品","pid":"01","value":""},{"id":"0113","name":"农业生产设备及用品","pid":"01","value":""},{"id":"0114","name":"花卉/苗木/园林","pid":"01","value":""},{"id":"0201","name":"餐饮","pid":"02","value":""},{"id":"0202","name":"住宿","pid":"02","value":""},{"id":"0203","name":"休闲/养生/娱乐","pid":"02","value":""},{"id":"0204","name":"教育/培训/咨询","pid":"02","value":""},{"id":"0205","name":"医疗","pid":"02","value":""},{"id":"0206","name":"旅游","pid":"02","value":""},{"id":"0207","name":"缴费","pid":"02","value":""},{"id":"0208","name":"租赁","pid":"02","value":""},{"id":"0209","name":"维修","pid":"02","value":""},{"id":"0210","name":"家政/干洗","pid":"02","value":""},{"id":"0211","name":"照相/摄影","pid":"02","value":""},{"id":"0212","name":"广告设计","pid":"02","value":""},{"id":"0213","name":"物流/快递","pid":"02","value":""},{"id":"0214","name":"停车/物业","pid":"02","value":""},{"id":"0215","name":"福利彩票","pid":"02","value":""},{"id":"010101","name":"便利店","pid":"0101","value":"5331"},{"id":"010102","name":"百货超市","pid":"0101","value":"5311"},{"id":"010103","name":"大型超市/卖场","pid":"0101","value":"5399"},{"id":"010201","name":"服装/鞋帽/袜子/配饰","pid":"0102","value":"5699"},{"id":"010202","name":"眼镜","pid":"0102","value":"8043"},{"id":"010203","name":"手表/手环","pid":"0102","value":"5944"},{"id":"010301","name":"烟酒/茶叶","pid":"0103","value":"5411"},{"id":"010302","name":"副食/糖果/饮品/奶制品","pid":"0103","value":"5411"},{"id":"010303","name":"粮油/调料","pid":"0103","value":"5411"},{"id":"010304","name":"生鲜/蔬菜/水果","pid":"0103","value":"5411"},{"id":"010305","name":"特产","pid":"0103","value":"5411"},{"id":"010401","name":"房地产开发销售","pid":"0104","value":"1520"},{"id":"010402","name":"二手房销售","pid":"0104","value":"7013"},{"id":"010501","name":"瓷砖/石材","pid":"0105","value":"5211"},{"id":"010502","name":"油漆/涂料/墙纸","pid":"0105","value":"5231"},{"id":"010503","name":"门框/板材","pid":"0105","value":"5211"},{"id":"010504","name":"钢材/铝材/玻璃","pid":"0105","value":"5211"},{"id":"010505","name":"五金/电线/电缆/安防器材","pid":"0105","value":"5251"},{"id":"010506","name":"家具/厨卫/灯饰","pid":"0105","value":"5712"},{"id":"010507","name":"家纺用品/窗帘布艺","pid":"0105","value":"5714"},{"id":"010508","name":"玉器/画饰/工艺美术品等装饰品","pid":"0105","value":"5970"},{"id":"010601","name":"洗护用品/化妆品","pid":"0106","value":"5977"},{"id":"010602","name":"日杂用品","pid":"0106","value":"5331"},{"id":"010603","name":"箱包/皮具","pid":"0106","value":"5948"},{"id":"010604","name":"布匹/轻纺","pid":"0106","value":"5949"},{"id":"010701","name":"办公家具及其它办公用品","pid":"0107","value":"5021"},{"id":"010702","name":"计算机及外围设备/电脑耗材/网络设备","pid":"0107","value":"5045"},{"id":"010703","name":"文具/书刊杂志","pid":"0107","value":"5942"},{"id":"010704","name":"音像制品","pid":"0107","value":"5735"},{"id":"010705","name":"体育用品/健生器材","pid":"0107","value":"5941"},{"id":"010706","name":"音乐商店—乐器、钢琴、乐谱","pid":"0107","value":"5733"},{"id":"010707","name":"玩具/麻将桌等娱乐器材","pid":"0107","value":"5943"},{"id":"010801","name":"礼品","pid":"0108","value":"5947"},{"id":"010802","name":"鲜花","pid":"0108","value":"5992"},{"id":"010803","name":"婚庆用品","pid":"0108","value":"5947"},{"id":"010901","name":"家电产品及配件","pid":"0109","value":"5722"},{"id":"010902","name":"手机及配件","pid":"0109","value":"5722"},{"id":"010903","name":"数码相机/照相器材","pid":"0109","value":"5044"},{"id":"011001","name":"加油站、收费站","pid":"0110","value":"5542"},{"id":"011002","name":"汽车销售(4S店/汽车商行/二手车行等)","pid":"0110","value":"5521"},{"id":"011003","name":"汽车配件销售/汽车美容装饰","pid":"0110","value":"5592"},{"id":"011004","name":"电动车/摩托车及其它机动车销售/配件销售","pid":"0110","value":"5571"},{"id":"011005","name":"自行车及其它代步工具销售/配件销售","pid":"0110","value":"5940"},{"id":"011006","name":"旅行箱包/帐篷等旅行设备","pid":"0110","value":"5948"},{"id":"011101","name":"药品/保健品","pid":"0111","value":"5912"},{"id":"011102","name":"医疗设备/医疗器材","pid":"0111","value":"5047"},{"id":"011103","name":"残疾人设备","pid":"0111","value":"5047"},{"id":"011201","name":"五金/电线/电缆","pid":"0112","value":"5251"},{"id":"011202","name":"电器设备","pid":"0112","value":"5251"},{"id":"011203","name":"机电设备及配件销售","pid":"0112","value":"5251"},{"id":"011301","name":"种植、养殖、畜牧等农业生产活动","pid":"0113","value":"9708"},{"id":"011302","name":"农药化肥、种子及其它农产品","pid":"0113","value":"9708"},{"id":"011303","name":"农机及配件","pid":"0113","value":"9708"},{"id":"011401","name":"花木栽种用品、苗木和花卉","pid":"0114","value":"5193"},{"id":"011402","name":"石雕/园林装饰产品","pid":"0114","value":"8912"},{"id":"020101","name":"餐馆/农庄","pid":"0201","value":"5812"},{"id":"020102","name":"早餐售卖点/宵夜摊","pid":"0201","value":"5812"},{"id":"020103","name":"茶楼","pid":"0201","value":"5812"},{"id":"020104","name":"蛋糕店/奶茶店","pid":"0201","value":"5812"},{"id":"020201","name":"酒店/宾馆","pid":"0202","value":"7011"},{"id":"020202","name":"度假村","pid":"0202","value":"7011"},{"id":"020301","name":"理发店/发廊","pid":"0203","value":"7230"},{"id":"020302","name":"美容店/美妆","pid":"0203","value":"7230"},{"id":"020303","name":"酒吧/KTV/娱乐会所","pid":"0203","value":"5813"},{"id":"020304","name":"健生/按摩/足浴及其它休闲养生场所","pid":"0203","value":"7298"},{"id":"020305","name":"桌游/桌球","pid":"0203","value":"7932"},{"id":"020306","name":"网吧/电玩","pid":"0203","value":"7994"},{"id":"020307","name":"电影院","pid":"0203","value":"7832"},{"id":"020401","name":"学校/教育机构","pid":"0204","value":"8299"},{"id":"020402","name":"培训机构","pid":"0204","value":"8299"},{"id":"020403","name":"咨询机构","pid":"0204","value":"8299"},{"id":"020501","name":"医院","pid":"0205","value":"8062"},{"id":"020502","name":"诊所","pid":"0205","value":"8099"},{"id":"020601","name":"交通运输售票处","pid":"0206","value":"4111"},{"id":"020602","name":"铁路运输","pid":"0206","value":"4112"},{"id":"020603","name":"旅行社","pid":"0206","value":"4733"},{"id":"020604","name":"景区售票处","pid":"0206","value":"4722"},{"id":"020701","name":"水电、煤气等便民缴费点","pid":"0207","value":"4900"},{"id":"020702","name":"电信缴费点","pid":"0207","value":"4814"},{"id":"020801","name":"房屋中介","pid":"0208","value":"7013"},{"id":"020802","name":"租车公司","pid":"0208","value":"5511"},{"id":"020803","name":"租船公司","pid":"0208","value":"5551"},{"id":"020901","name":"家电维修店","pid":"0209","value":"7629"},{"id":"020902","name":"汽车及其它机动车维修保养站","pid":"0209","value":"7538"},{"id":"020903","name":"摩托车维修站","pid":"0209","value":"5598"},{"id":"020904","name":"自行车维修站","pid":"0209","value":"5940"},{"id":"021001","name":"家政服务公司","pid":"0210","value":"7295"},{"id":"021002","name":"干洗店","pid":"0210","value":"7216"},{"id":"021101","name":"照相馆","pid":"0211","value":"7395"},{"id":"021102","name":"婚纱摄影店","pid":"0211","value":"7333"},{"id":"021103","name":"摄影工作室","pid":"0211","value":"7221"},{"id":"021201","name":"广告设计制","pid":"0212","value":"7311"},{"id":"021202","name":"复印/打印","pid":"0212","value":"7338"},{"id":"021301","name":"物流公司","pid":"0213","value":"4215"},{"id":"021302","name":"快递公司","pid":"0213","value":"4215"},{"id":"021401","name":"停车场","pid":"0214","value":"7523"},{"id":"021402","name":"物业管理","pid":"0214","value":"7013"},{"id":"021501","name":"福利彩票","pid":"0215","value":"7995"},{"id":"021502","name":"体育彩票","pid":"0215","value":"7995"}]
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MultilevelStlyeMenu.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelStlyeMenu.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/5/14.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public typealias SelectResultClosure = (String, MenuDataModel) -> Void
12 |
13 | public class MultilevelStlyeMenu: UIView {
14 |
15 | ///false表示你必须要选择最后一级的数据才可以点确认按钮;true表示你可以选择任意一级的数据,然后确认结果
16 | @objc public var allowSelectAnyLevelData = false
17 | ///当前列表是第几级
18 | var currentLevel: Int = 1
19 | ///当前级别的行是否有下一级别的数据
20 | var hasNextLevel = true
21 | ///是否选中了最后一级列表的行
22 | var isSelectLastLevelRow = false
23 | var titleText: String?
24 | var allDataSource: [MenuDataModel] = []
25 | var firstMenuDataSource: [MenuDataModel] = []
26 | var modelSelected = MenuDataModel()
27 | var completion: SelectResultClosure?
28 | var defalutOption: MultilevelMenuOption = MultilevelMenuOption()
29 | var upperBarView: UIView!
30 | var reminderLabel: UILabel!
31 | var scrollView: UIScrollView!
32 | var currentButton: UIButton?
33 | var buttonTotalWidth: CGFloat = 0
34 |
35 | //MARK: - init
36 | override init(frame: CGRect) {
37 | super.init(frame: frame)
38 | layOut()
39 | }
40 |
41 | required public init?(coder aDecoder: NSCoder) {
42 | fatalError("init(coder:) has not been implemented")
43 | }
44 |
45 | //MARK: - Handle Data
46 | func getDataSourceFromJsonFile(_ url: URL) -> [MenuDataModel] {
47 | var dataSouce: [MenuDataModel] = []
48 | do{
49 | let data = try Data(contentsOf: url)
50 | let json:Any = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.mutableContainers)
51 | if let jsonArray = json as? [[String: String]] {
52 | for dict in jsonArray {
53 | let model = MenuDataModel.init(dict: dict)
54 | dataSouce.append(model)
55 | }
56 | }
57 | }catch let erro as Error?{
58 | print("读取本地数据出现错误!",erro!)
59 | }
60 | return dataSouce
61 | }
62 |
63 | func setFirstDataSource() {
64 | var tempDataSouce = [MenuDataModel]()
65 | for data in self.allDataSource {
66 | if data.pid == nil || data.pid == "" {
67 | tempDataSouce.append(data)
68 | }
69 | }
70 | self.firstMenuDataSource = tempDataSouce
71 | }
72 |
73 | func getNextLevelDataSouce(_ id: String?) -> [MenuDataModel] {
74 | var tempDataSouce = [MenuDataModel]()
75 | for data in self.allDataSource {
76 | if data.pid == id {
77 | tempDataSouce.append(data)
78 | }
79 | }
80 | return tempDataSouce
81 | }
82 |
83 | //MARK: - Show & Cancel
84 | @objc public func show() {
85 |
86 | }
87 |
88 | @objc func cancelAction() {
89 |
90 | }
91 |
92 | //MARK: - Layout
93 | func layOut() {
94 |
95 | }
96 |
97 | func layOutMenuView() {
98 |
99 | }
100 |
101 | func creatNextLevelMenuView(_ dataSouce: [MenuDataModel]) {
102 |
103 | }
104 |
105 | //MARK: - Scroll Button
106 | func selectResultDisplay(_ name: String?) {
107 | if hasNextLevel {
108 | isSelectLastLevelRow = false
109 | if currentButton == nil {
110 | creatDisplayButton(name)
111 | } else {
112 | if (currentButton?.tag)! - 200 != currentLevel {
113 | creatDisplayButton(name)
114 | } else {
115 | resetDisplayButton(name)
116 | }
117 | }
118 | } else {
119 | if isSelectLastLevelRow == false {
120 | if currentButton == nil {
121 | creatDisplayButton(name)
122 | } else if (currentButton?.tag)! - 200 != currentLevel {
123 | creatDisplayButton(name)
124 | isSelectLastLevelRow = true
125 | } else {
126 | resetDisplayButton(name)
127 | }
128 | } else {
129 | if currentButton == nil {
130 | creatDisplayButton(name)
131 | } else {
132 | resetDisplayButton(name)
133 | }
134 | }
135 | }
136 | }
137 |
138 | func creatDisplayButton(_ name: String?) {
139 | let buttonH = upperBarView.frame.height
140 | var text: String?
141 | if currentLevel == 1 {
142 | text = name
143 | } else {
144 | text = " > \(name ?? "")"
145 | }
146 | let buttonW_Text = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: buttonH), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)], context: nil).width
147 | let buttonW = buttonW_Text ?? 48
148 | let button = UIButton(frame: CGRect(x: buttonTotalWidth, y: 0, width: buttonW , height: buttonH))
149 | self.buttonTotalWidth += buttonW
150 | button.setTitleColor(defalutOption.upperBarButtonColor, for: .normal)
151 | button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
152 | button.tag = 200 + currentLevel
153 | if currentLevel == 1 {
154 | button.setTitle(name, for: .normal)
155 | } else {
156 | let attributedStr = NSMutableAttributedString.init(string: text ?? " ")
157 | attributedStr.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.darkGray], range: NSRange(location: 2, length: 1))
158 | button.titleLabel?.textColor = defalutOption.upperBarButtonColor
159 | button.titleLabel?.attributedText = attributedStr
160 | button.setAttributedTitle(attributedStr, for: .normal)
161 | }
162 | button.addTarget(self, action: #selector(clickName(_:)), for: .touchUpInside)
163 | currentButton = button
164 | scrollView.addSubview(button)
165 | if self.buttonTotalWidth > scrollView.frame.width {
166 | scrollView.contentSize = CGSize(width: buttonTotalWidth, height: 0)
167 | scrollView.showsHorizontalScrollIndicator = true
168 | scrollView.flashScrollIndicators()
169 | }
170 | }
171 |
172 | func resetDisplayButton(_ name: String?) {
173 | let buttonH = upperBarView.frame.height
174 | var text: String?
175 | if currentLevel == 1 {
176 | text = name
177 | } else {
178 | text = " > \(name ?? "")"
179 | }
180 | let buttonW_Text = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: buttonH), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)], context: nil).width
181 | let buttonW = buttonW_Text ?? 48
182 | let currentButtonW = currentButton?.bounds.size.width
183 | currentButton?.frame.size = CGSize(width: buttonW, height: buttonH)
184 | if currentLevel == 1 {
185 | currentButton?.setTitle(name, for: .normal)
186 | } else {
187 | let attributedStr = NSMutableAttributedString.init(string: text ?? " ")
188 | attributedStr.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.darkGray], range: NSRange(location: 2, length: 1))
189 | currentButton?.titleLabel?.textColor = defalutOption.upperBarButtonColor
190 | currentButton?.titleLabel?.attributedText = attributedStr
191 | currentButton?.setAttributedTitle(attributedStr, for: .normal)
192 | }
193 | self.buttonTotalWidth += (buttonW - currentButtonW!)
194 | scrollView.contentSize = CGSize(width: buttonTotalWidth, height: 0)
195 | }
196 |
197 | func removeDisplayButton(_ tag: Int) {
198 | if let button = scrollView.viewWithTag(tag) as? UIButton {
199 | button.removeFromSuperview()
200 | self.buttonTotalWidth -= button.frame.size.width
201 | scrollView.contentSize = CGSize(width: buttonTotalWidth, height: 0)
202 | }
203 | }
204 |
205 | @objc func clickName(_ sender: UIButton) {
206 |
207 | }
208 |
209 | // MARK: - Result Handle
210 | @objc func confirm() {
211 | if completion != nil {
212 | let combinedResultSting = getCombinedResultString()
213 | completion!(combinedResultSting, modelSelected)
214 | }
215 | cancelAction()
216 | }
217 |
218 | func getCombinedResultString() -> String {
219 | var string = ""
220 | for i in 1 ... currentLevel {
221 | if let button = scrollView.viewWithTag(i + 200) as? UIButton {
222 | string += (button.titleLabel?.text)!
223 | }
224 | }
225 | string = string.replacingOccurrences(of: " ", with: "")
226 | string = string.replacingOccurrences(of: ">", with: " ")
227 | return string
228 | }
229 |
230 | }
231 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MultilevelStyle1Menu.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelPicker.swift
3 | // FWOMSMerchant
4 | //
5 | // Created by ChokShen on 2018/5/10.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class MultilevelStyle1Menu: MultilevelStlyeMenu, MultilevelMenuStlye1ViewDelegate {
12 |
13 | override var hasNextLevel: Bool {
14 | didSet {
15 | if allowSelectAnyLevelData == false {
16 | if hasNextLevel == false {
17 | setConfirmBtn(true)
18 | } else {
19 | setConfirmBtn(false)
20 | }
21 | }
22 | }
23 | }
24 | static let upperViewHeight: CGFloat = 44
25 | static let height: CGFloat = MMScreen.isFullScreen ? 352 + MMScreen.bottomSafeHeight : 352
26 | static let confirmButtonHeight: CGFloat = 44
27 | private var tableViewFrame: CGRect {
28 | return CGRect(x: 0, y: MultilevelStyle1Menu.upperViewHeight, width: MMScreen.width, height: MultilevelStyle1Menu.height - MultilevelStyle1Menu.upperViewHeight - MultilevelStyle1Menu.confirmButtonHeight - MMScreen.bottomSafeHeight)
29 | }
30 | private var firstMenuView: MultilevelMenuStyle1View!
31 | private var customMenuView: MultilevelMenuStyle1View?
32 | private var confirmButton: UIButton!
33 | private lazy var containerView: UIView = {
34 | let containerView = UIView()
35 | containerView.frame = CGRect(x: 0, y: 0, width: MMScreen.width, height: MMScreen.height - MultilevelStyle1Menu.height)
36 | containerView.backgroundColor = UIColor.protectedBackgroundColor
37 | containerView.isUserInteractionEnabled = true
38 | containerView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.cancelAction)))
39 | return containerView
40 | }()
41 |
42 | //MARK: - init
43 | @objc public convenience init(title: String?,
44 | fileUrl: URL,
45 | option: MultilevelMenuOption? = nil,
46 | customView: MultilevelMenuStyle1View? = nil,
47 | completion: SelectResultClosure?) {
48 | self.init(frame: CGRect(x: 0, y: MMScreen.height, width: MMScreen.width, height: MultilevelStyle1Menu.height))
49 | self.allDataSource = getDataSourceFromJsonFile(fileUrl)
50 | self.titleText = title
51 | if option != nil {
52 | self.defalutOption = option!
53 | } else {
54 | self.defalutOption = MultilevelMenuOption()
55 | }
56 | self.completion = completion
57 | self.customMenuView = customView
58 | layOut()
59 | setFirstDataSource()
60 | }
61 |
62 | @objc public convenience init(title: String?,
63 | dataSouce: [MenuDataModel],
64 | option: MultilevelMenuOption? = nil,
65 | customView: MultilevelMenuStyle1View? = nil,
66 | completion: SelectResultClosure?) {
67 | self.init(frame: CGRect(x: 0, y: MMScreen.height, width: MMScreen.width, height: MultilevelStyle1Menu.height))
68 | self.allDataSource = dataSouce
69 | self.titleText = title
70 | if option != nil {
71 | self.defalutOption = option!
72 | } else {
73 | self.defalutOption = MultilevelMenuOption()
74 | }
75 | self.completion = completion
76 | self.customMenuView = customView
77 | layOut()
78 | setFirstDataSource()
79 | }
80 |
81 | override init(frame: CGRect) {
82 | super.init(frame: frame)
83 | }
84 |
85 | private func initMultilevelMenuView() -> MultilevelMenuStyle1View {
86 | if customMenuView == nil {
87 | return MultilevelMenuStyle1View()
88 | } else {
89 | let className = String(describing: type(of: customMenuView!))
90 | let projectName = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
91 | let multilevelMenuView = NSClassFromString(projectName + "." + className) as! MultilevelMenuStyle1View.Type
92 | return multilevelMenuView.init()
93 | }
94 | }
95 |
96 | required public init?(coder aDecoder: NSCoder) {
97 | fatalError("init(coder:) has not been implemented")
98 | }
99 |
100 | //MARK: - Handle Data
101 | override func setFirstDataSource() {
102 | super.setFirstDataSource()
103 | reminderLabel.text = self.titleText
104 | firstMenuView.dataSouce = firstMenuDataSource
105 | }
106 |
107 | //MARK: - Show & Cancel
108 | @objc override public func show() {
109 | if allowSelectAnyLevelData {
110 | setConfirmBtn(true)
111 | } else {
112 | setConfirmBtn(false)
113 | }
114 | // 通过window 弹出view
115 | guard let window = UIApplication.shared.delegate?.window else { return }
116 | guard let currentWindow = window else { return }
117 | UIView.animate(withDuration: 0.3, animations: {
118 | self.frame.origin = CGPoint(x: 0, y: MMScreen.height - MultilevelStyle1Menu.height)
119 | currentWindow.addSubview(self)
120 | }) { (finished) in
121 | if finished {
122 | currentWindow.addSubview(self.containerView)
123 | }
124 | }
125 | }
126 |
127 | @objc override func cancelAction() {
128 | self.containerView.removeFromSuperview()
129 | UIView.animate(withDuration: 0.3, animations: {
130 | self.frame.origin = CGPoint(x: 0, y: MMScreen.height)
131 | }) { (finished) in
132 | if finished {
133 | self.removeFromSuperview()
134 | }
135 | }
136 | }
137 |
138 | //MARK: - Layout
139 | override func layOut() {
140 | self.backgroundColor = UIColor.white
141 | layOutUpperView()
142 | layOutMenuView()
143 | layOutConfirmButton()
144 | }
145 |
146 | override func layOutMenuView() {
147 | firstMenuView = initMultilevelMenuView()
148 | firstMenuView.frame = tableViewFrame
149 | firstMenuView.option = self.defalutOption
150 | firstMenuView.isFirst = true
151 | firstMenuView.delegate = self
152 | firstMenuView.tag = currentLevel
153 | self.addSubview(firstMenuView)
154 | }
155 |
156 | override func creatNextLevelMenuView(_ dataSouce: [MenuDataModel]) {
157 | let nextMenuView = initMultilevelMenuView()
158 | nextMenuView.frame = tableViewFrame
159 | nextMenuView.option = self.defalutOption
160 | nextMenuView.isFirst = false
161 | nextMenuView.delegate = self
162 | nextMenuView.dataSouce = dataSouce
163 | nextMenuView.tag = currentLevel
164 | self.addSubview(nextMenuView)
165 | }
166 |
167 | private func layOutUpperView() {
168 | upperBarView = UIView(frame: CGRect(x: 0, y: 0, width: MMScreen.width, height: MultilevelStyle1Menu.upperViewHeight))
169 | upperBarView.backgroundColor = UIColor.white
170 | self.addSubview(upperBarView)
171 |
172 | //提示标签
173 | reminderLabel = UILabel(frame: CGRect(x: 15, y: 0, width: 70, height: upperBarView.frame.height - 0.5))
174 | reminderLabel.font = UIFont.systemFont(ofSize: 16)
175 | reminderLabel.text = self.titleText
176 | reminderLabel.textColor = UIColor.black
177 | upperBarView.addSubview(reminderLabel)
178 | //滚动视图
179 | let scrollViewX = reminderLabel.frame.maxX + 15
180 | scrollView = UIScrollView(frame: CGRect(x: scrollViewX, y: 0, width: MMScreen.width - scrollViewX, height: upperBarView.frame.height - 0.5))
181 | scrollView.showsHorizontalScrollIndicator = false
182 | scrollView.contentSize = CGSize(width: scrollView.frame.width, height: 0)
183 | upperBarView.addSubview(scrollView)
184 | //分割线
185 | let seperator = UILabel(frame: CGRect(x: 0, y: reminderLabel.frame.maxY, width: upperBarView.frame.width, height: 0.5))
186 | seperator.backgroundColor = UIColor.seperatorLineColor
187 | upperBarView.addSubview(seperator)
188 | }
189 |
190 | private func layOutConfirmButton() {
191 | confirmButton = UIButton(type: .custom)
192 | confirmButton.frame = CGRect(x: 0, y: tableViewFrame.maxY, width: MMScreen.width, height: MultilevelStyle1Menu.confirmButtonHeight)
193 | confirmButton.setTitle(self.defalutOption.bottomButtonTitle, for: .normal)
194 | confirmButton.titleLabel?.font = UIFont.systemFont(ofSize: 18)
195 | confirmButton.setTitleColor(UIColor.white, for: .normal)
196 | confirmButton.setBackgroundImage(UIImage.imageWithColor(self.defalutOption.bottomButtonBackgroundColor_Disable), for: .normal)
197 | confirmButton.setBackgroundImage(UIImage.imageWithColor(self.defalutOption.bottomButtonBackgroundColor_Highlighted), for: .highlighted)
198 | confirmButton.addTarget(self, action: #selector(confirm), for: .touchUpInside)
199 | self.addSubview(confirmButton)
200 | setConfirmBtn(false)
201 | }
202 |
203 | private func setConfirmBtn(_ enabled: Bool) {
204 | self.confirmButton.isEnabled = enabled
205 | if enabled {
206 | self.confirmButton.setBackgroundImage(UIImage.imageWithColor(self.defalutOption.bottomButtonBackgroundColor_Normal), for: .normal)
207 | } else {
208 | self.confirmButton.setBackgroundImage(UIImage.imageWithColor(self.defalutOption.bottomButtonBackgroundColor_Disable), for: .normal)
209 | }
210 | }
211 |
212 | //MARK: - Animation
213 | private func listViewHideAnimation(_ tag: Int, _ completion: AnimationCompletionClosure? = nil) {
214 | if let listView = self.viewWithTag(tag) as? MultilevelMenuStyle1View {
215 | listView.hideAnimation(completion)
216 | }
217 | }
218 |
219 | private func listViewRemoveFromSuperView(_ tag: Int) {
220 | if let listView = self.viewWithTag(tag) as? MultilevelMenuStyle1View {
221 | listView.removeFromSuperview()
222 | }
223 | }
224 |
225 | //MARK: - Scroll Button
226 | @objc override func clickName(_ sender: UIButton) {
227 | let clickedLevel = sender.tag - 200
228 | if clickedLevel < currentLevel {
229 | listViewHideAnimation(currentLevel, { (completion) in
230 | if completion {
231 | for i in (clickedLevel + 1) ..< self.currentLevel {
232 | self.listViewRemoveFromSuperView(i)
233 | }
234 | let low = clickedLevel + 1
235 | for j in low ... self.currentLevel {
236 | self.removeDisplayButton(j + 200)
237 | }
238 | self.isSelectLastLevelRow = false
239 | self.currentLevel = clickedLevel
240 | self.currentButton = self.scrollView.viewWithTag(self.currentLevel + 200) as? UIButton
241 | }
242 | })
243 | hasNextLevel = true
244 | }
245 | }
246 |
247 | // MARK: - PickerListViewDelegate
248 | public func didSelectRow(_ listView: MultilevelMenuStyle1View, _ row: Int, _ dateModel: MenuDataModel) {
249 | modelSelected = dateModel
250 | let nextLevelDataSouce = self.getNextLevelDataSouce(dateModel.id)
251 | hasNextLevel = nextLevelDataSouce.isEmpty ? false : true
252 | selectResultDisplay(dateModel.name)
253 | if hasNextLevel {
254 | currentLevel += 1
255 | creatNextLevelMenuView(nextLevelDataSouce)
256 | }
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/MultilevelMenu/Source/MultilevelStyle2Menu.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilevelMenuController.swift
3 | // MultilevelMenuDemo
4 | //
5 | // Created by ChokShen on 2018/4/27.
6 | // Copyright © 2018年 shenzhiqiang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class MultilevelStyle2Menu: MultilevelStlyeMenu, MultilevelMenuStlye2ViewDelegate{
12 |
13 | override var hasNextLevel: Bool {
14 | didSet {
15 | if allowSelectAnyLevelData == false {
16 | if hasNextLevel == false {
17 | setConfirmBtn(true)
18 | } else {
19 | setConfirmBtn(false)
20 | }
21 | }
22 | }
23 | }
24 | static let upperViewHeight: CGFloat = 44
25 | private var defalutFrame: CGRect {
26 | return CGRect(x: 0, y: MMScreen.navigationHeight + MultilevelStyle2Menu.upperViewHeight, width: MMScreen.width, height: MMScreen.height - MMScreen.navigationHeight - MultilevelStyle2Menu.upperViewHeight)
27 | }
28 | private var firstMenuView: MultilevelMenuStyle2View!
29 | private var customMenuView: MultilevelMenuStyle2View?
30 | private var navigationBar: UIView!
31 | private var titltLabel: UILabel!
32 | private var confirmButton: UIButton!
33 | private var cancelButton: UIButton!
34 |
35 | //MARK: - init
36 | /// 初始化
37 | ///
38 | /// - Parameters:
39 | /// - title: 标题
40 | /// - fileUrl: 文件的路径
41 | /// - option: 菜单的参数配置
42 | /// - customView: 自定义视图
43 | /// - completion: 选择结果的回调
44 | @objc public convenience init(title: String?,
45 | fileUrl: URL,
46 | option: MultilevelMenuOption? = nil,
47 | customView: MultilevelMenuStyle2View? = nil,
48 | completion: SelectResultClosure?) {
49 | self.init(frame: CGRect(x: 0, y: MMScreen.height, width: MMScreen.width, height: MMScreen.height))
50 | self.allDataSource = getDataSourceFromJsonFile(fileUrl)
51 | self.titleText = title
52 | if option != nil {
53 | self.defalutOption = option!
54 | } else {
55 | self.defalutOption = MultilevelMenuOption()
56 | }
57 | self.completion = completion
58 | self.customMenuView = customView
59 | layOut()
60 | setFirstDataSource()
61 | }
62 |
63 | /// 初始化
64 | ///
65 | /// - Parameters:
66 | /// - title: 标题
67 | /// - dataSouce: 数据源
68 | /// - option: 菜单的参数配置
69 | /// - customView: 自定义视图
70 | /// - completion: 选择结果的回调
71 | @objc public convenience init(title: String?,
72 | dataSouce: [MenuDataModel],
73 | option: MultilevelMenuOption? = nil,
74 | customView: MultilevelMenuStyle2View? = nil,
75 | completion: SelectResultClosure?) {
76 | self.init(frame: CGRect(x: 0, y: MMScreen.height, width: MMScreen.width, height: MMScreen.height))
77 | self.allDataSource = dataSouce
78 | self.titleText = title
79 | if option != nil {
80 | self.defalutOption = option!
81 | } else {
82 | self.defalutOption = MultilevelMenuOption()
83 | }
84 | self.completion = completion
85 | self.customMenuView = customView
86 | layOut()
87 | setFirstDataSource()
88 | }
89 |
90 | override init(frame: CGRect) {
91 | super.init(frame: frame)
92 | }
93 |
94 | private func initMultilevelMenuView() -> MultilevelMenuStyle2View {
95 | if customMenuView == nil {
96 | return MultilevelMenuStyle2View()
97 | } else {
98 | let className = String(describing: type(of: customMenuView!))
99 | let projectName = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
100 | let multilevelMenuView = NSClassFromString(projectName + "." + className) as! MultilevelMenuStyle2View.Type
101 | return multilevelMenuView.init()
102 | }
103 | }
104 |
105 | required public init?(coder aDecoder: NSCoder) {
106 | fatalError("init(coder:) has not been implemented")
107 | }
108 |
109 | //MARK: - Layout
110 | override func layOut() {
111 | self.backgroundColor = UIColor.white
112 | layOutMenuView()
113 | layOutCustomStatusBar()
114 | layOutCustomNavigationBar()
115 | layOutUpperView()
116 | }
117 |
118 | override func layOutMenuView() {
119 | firstMenuView = initMultilevelMenuView()
120 | firstMenuView.frame = defalutFrame
121 | firstMenuView.option = self.defalutOption
122 | firstMenuView.isFirst = true
123 | firstMenuView.delegate = self
124 | firstMenuView.tag = currentLevel
125 | self.addSubview(firstMenuView)
126 | }
127 |
128 | override func creatNextLevelMenuView(_ dataSouce: [MenuDataModel]) {
129 | let nextMenuView = initMultilevelMenuView()
130 | nextMenuView.frame = defalutFrame
131 | nextMenuView.option = self.defalutOption
132 | nextMenuView.isFirst = false
133 | nextMenuView.delegate = self
134 | nextMenuView.dataSouce = dataSouce
135 | nextMenuView.tag = currentLevel
136 | self.addSubview(nextMenuView)
137 | }
138 |
139 | private func layOutCustomStatusBar() {
140 | //自定义状态栏
141 | let statusBar = UIView(frame: CGRect(x: 0, y: 0, width: MMScreen.width, height: MMScreen.statusBarHeight))
142 | statusBar.backgroundColor = defalutOption.navigationBarColor
143 | self.addSubview(statusBar)
144 | }
145 |
146 | private func layOutCustomNavigationBar() {
147 | //自定义导航栏
148 | navigationBar = UIView(frame: CGRect(x: 0, y: MMScreen.statusBarHeight, width: MMScreen.width, height: MMScreen.navigationBarHeight))
149 | navigationBar.backgroundColor = defalutOption.navigationBarColor
150 | self.addSubview(navigationBar)
151 | let leftEdge: CGFloat = 15
152 | //1.确定按钮
153 | confirmButton = UIButton(type: .custom)
154 | confirmButton.frame = CGRect(x: MMScreen.width - leftEdge - 50, y: (navigationBar.frame.height - 30) / 2, width: 50, height: 30)
155 | confirmButton.contentHorizontalAlignment = .right
156 | confirmButton.setTitle(self.defalutOption.rightBarButtonTitle, for: .normal)
157 | confirmButton.titleLabel?.font = UIFont.systemFont(ofSize: 18)
158 | confirmButton.setTitleColor(self.defalutOption.rightBarButtonColor, for: .normal)
159 | confirmButton.addTarget(self, action: #selector(confirm), for: .touchUpInside)
160 | setConfirmBtn(true)
161 | navigationBar.addSubview(confirmButton)
162 | //2.取消按钮
163 | cancelButton = UIButton(type: .custom)
164 | cancelButton.frame = CGRect(x: leftEdge, y: (navigationBar.frame.height - 18) / 2, width: 18, height: 18)
165 | let bundle = Bundle(for: MultilevelStlyeMenu.self)
166 | let closeImage = UIImage(named: "MultilevelMenuBundle.bundle/btn_common_close_wh", in: bundle, compatibleWith: nil)
167 | cancelButton.setImage(closeImage?.imageMaskWithColor(self.defalutOption.closeButtonColor), for: .normal)
168 | cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
169 | navigationBar.addSubview(cancelButton)
170 | //3.标题
171 | titltLabel = UILabel(frame: CGRect(x: cancelButton.frame.maxX + leftEdge, y: (navigationBar.frame.height - 30) / 2, width: MMScreen.width - confirmButton.frame.width - cancelButton.frame.width - 4 * leftEdge , height: 30))
172 | titltLabel.textAlignment = .center
173 | titltLabel.font = UIFont.boldSystemFont(ofSize: 18)
174 | titltLabel.textColor = defalutOption.navigationTitleColor
175 | navigationBar.addSubview(titltLabel)
176 | }
177 |
178 | private func setConfirmBtn(_ enabled: Bool) {
179 | confirmButton.isEnabled = enabled
180 | if enabled {
181 | confirmButton.setTitleColor(defalutOption.rightBarButtonColor, for: .normal)
182 | } else {
183 | confirmButton.setTitleColor(UIColor.init(white: 0.2, alpha: 0.5), for: .normal)
184 | }
185 | }
186 |
187 | private func layOutUpperView() {
188 | upperBarView = UIView(frame: CGRect(x: 0, y: navigationBar.frame.maxY, width: MMScreen.width, height: MultilevelStyle2Menu.upperViewHeight))
189 | upperBarView.backgroundColor = UIColor.white
190 | self.addSubview(upperBarView)
191 |
192 | reminderLabel = UILabel(frame: CGRect(x: 16, y: 0, width: 70, height: upperBarView.frame.height - 1))
193 | reminderLabel.font = defalutOption.upperBarLeftTextFont
194 | reminderLabel.text = defalutOption.upperBarDefalutLeftText
195 | reminderLabel.textColor = defalutOption.upperBarLeftTextColor
196 | upperBarView.addSubview(reminderLabel)
197 | let scrollViewX = reminderLabel.frame.maxX
198 | scrollView = UIScrollView(frame: CGRect(x: scrollViewX, y: 0, width: MMScreen.width - scrollViewX, height: upperBarView.frame.height - 1))
199 | scrollView.showsHorizontalScrollIndicator = false
200 | scrollView.contentSize = CGSize(width: scrollView.frame.width, height: 0)
201 | upperBarView.addSubview(scrollView)
202 |
203 | let seperatorLine = UILabel(frame: CGRect(x: 0, y: reminderLabel.frame.maxY, width: MMScreen.width, height: 1))
204 | seperatorLine.backgroundColor = UIColor.ColorFromRGB(rgbValue: 0xE1E1E1)
205 | upperBarView.addSubview(seperatorLine)
206 | }
207 |
208 | //MARK: - Handle Data
209 | override func setFirstDataSource() {
210 | super.setFirstDataSource()
211 | titltLabel.text = self.titleText
212 | firstMenuView.dataSouce = firstMenuDataSource
213 | }
214 |
215 | //MARK: - Show & Cancel
216 | @objc override public func show() {
217 | if allowSelectAnyLevelData {
218 | setConfirmBtn(true)
219 | } else {
220 | setConfirmBtn(false)
221 | }
222 | // 通过window 弹出view
223 | guard let window = UIApplication.shared.delegate?.window else { return }
224 | guard let currentWindow = window else { return }
225 | UIView.animate(withDuration: 0.3, animations: {
226 | self.frame.origin = CGPoint(x: 0, y: 0)
227 | currentWindow.addSubview(self)
228 | }) { (finished) in
229 | if finished {
230 | }
231 | }
232 | }
233 |
234 | @objc override func cancelAction() {
235 | UIView.animate(withDuration: 0.3, animations: {
236 | self.frame.origin = CGPoint(x: 0, y: MMScreen.height)
237 | }) { (finished) in
238 | if finished {
239 | self.removeFromSuperview()
240 | }
241 | }
242 | }
243 |
244 | //MARK: - Animation
245 | private func menuViewFullAnimation(_ tag: Int) {
246 | if let menuView = self.viewWithTag(tag) as? MultilevelMenuStyle2View {
247 | menuView.fullAnimation()
248 | }
249 | }
250 |
251 | private func menuViewBackToOriginalAnimation(_ tag: Int, _ completion: AnimationCompletionClosure? = nil) {
252 | if let menuView = self.viewWithTag(tag) as? MultilevelMenuStyle2View {
253 | menuView.popFromRightAnimation(completion)
254 | }
255 | }
256 |
257 | private func menuViewHideAnimation(_ tag: Int, _ completion: AnimationCompletionClosure? = nil) {
258 | if let menuView = self.viewWithTag(tag) as? MultilevelMenuStyle2View {
259 | menuView.hideAnimation_ClickButton(completion)
260 | }
261 | }
262 |
263 | private func menuViewRemoveFromSuperView(_ tag: Int) {
264 | if let menuView = self.viewWithTag(tag) as? MultilevelMenuStyle2View {
265 | menuView.removeFromSuperview()
266 | }
267 | }
268 |
269 | //MARK: - Scroll Button
270 | override func selectResultDisplay(_ name: String?) {
271 | super.selectResultDisplay(name)
272 | reminderLabel.text = defalutOption.upperBarSelectedLeftText
273 | }
274 |
275 | @objc override func clickName(_ sender: UIButton) {
276 | let clickedLevel = sender.tag - 200
277 | if clickedLevel < currentLevel {
278 | menuViewHideAnimation(currentLevel, { (completion) in
279 | if completion {
280 | if clickedLevel != 1 {
281 | self.menuViewBackToOriginalAnimation(clickedLevel, { (completion) in
282 | if completion {
283 | for i in (clickedLevel + 1) ..< self.currentLevel {
284 | self.menuViewRemoveFromSuperView(i)
285 | }
286 | }
287 | })
288 | } else {
289 | for i in (clickedLevel + 1) ..< self.currentLevel {
290 | self.menuViewRemoveFromSuperView(i)
291 | }
292 | }
293 | let low = clickedLevel + 1
294 | for j in low ... self.currentLevel {
295 | self.removeDisplayButton(j + 200)
296 | }
297 | self.isSelectLastLevelRow = false
298 | self.currentLevel = clickedLevel
299 | self.currentButton = self.scrollView.viewWithTag(self.currentLevel + 200) as? UIButton
300 | }
301 | })
302 | hasNextLevel = true
303 | }
304 | }
305 |
306 | // MARK: - MultilevelMenuViewDelegate
307 | public func didSelectRow(_ menuView: MultilevelMenuStyle2View, _ row: Int, _ dataModel: MenuDataModel) {
308 | modelSelected = dataModel
309 | let nextLevelDataSouce = self.getNextLevelDataSouce(dataModel.id)
310 | hasNextLevel = nextLevelDataSouce.isEmpty ? false : true
311 | selectResultDisplay(dataModel.name)
312 | if hasNextLevel {
313 | menuViewFullAnimation(currentLevel)
314 | currentLevel += 1
315 | creatNextLevelMenuView(nextLevelDataSouce)
316 | }
317 | }
318 |
319 | public func didRemoveFromView(_ menuView: MultilevelMenuStyle2View) {
320 | let lastLevel = currentLevel - 1
321 | if lastLevel > 1 {
322 | menuViewBackToOriginalAnimation(lastLevel)
323 | }
324 | removeDisplayButton(currentLevel + 200)
325 | isSelectLastLevelRow = false
326 | currentLevel -= 1
327 | currentButton = scrollView.viewWithTag(currentLevel + 200) as? UIButton
328 | hasNextLevel = true
329 | }
330 |
331 | }
332 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuSwift/MultilevelMenu.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4993E82322FD5754001EEB63 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E80E22FD5753001EEB63 /* ViewController.swift */; };
11 | 4993E82722FD5754001EEB63 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4993E81422FD5753001EEB63 /* LaunchScreen.storyboard */; };
12 | 4993E82822FD5754001EEB63 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4993E81622FD5753001EEB63 /* Main.storyboard */; };
13 | 4993E82922FD5754001EEB63 /* businessType.json in Resources */ = {isa = PBXBuildFile; fileRef = 4993E81822FD5753001EEB63 /* businessType.json */; };
14 | 4993E82A22FD5754001EEB63 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4993E81922FD5753001EEB63 /* Assets.xcassets */; };
15 | 4993E82B22FD5754001EEB63 /* China.png in Resources */ = {isa = PBXBuildFile; fileRef = 4993E81B22FD5754001EEB63 /* China.png */; };
16 | 4993E82C22FD5754001EEB63 /* CustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4993E81C22FD5754001EEB63 /* CustomCell.xib */; };
17 | 4993E82D22FD5754001EEB63 /* CustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E81D22FD5754001EEB63 /* CustomCell.swift */; };
18 | 4993E82E22FD5754001EEB63 /* CustomMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E81E22FD5754001EEB63 /* CustomMenuView.swift */; };
19 | 4993E82F22FD5754001EEB63 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E81F22FD5754001EEB63 /* AppDelegate.swift */; };
20 | 4993E83F22FD57B0001EEB63 /* MultilevelMenuBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4993E83422FD57B0001EEB63 /* MultilevelMenuBundle.bundle */; };
21 | 4993E84022FD57B0001EEB63 /* MenuDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83622FD57B0001EEB63 /* MenuDataModel.swift */; };
22 | 4993E84122FD57B0001EEB63 /* MultilevelMenuOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83722FD57B0001EEB63 /* MultilevelMenuOption.swift */; };
23 | 4993E84222FD57B0001EEB63 /* MultilevelStyle2Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83822FD57B0001EEB63 /* MultilevelStyle2Menu.swift */; };
24 | 4993E84322FD57B0001EEB63 /* MenuMarco.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83922FD57B0001EEB63 /* MenuMarco.swift */; };
25 | 4993E84422FD57B0001EEB63 /* MultilevelMenuStyle1View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83A22FD57B0001EEB63 /* MultilevelMenuStyle1View.swift */; };
26 | 4993E84522FD57B0001EEB63 /* MultilevelMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83B22FD57B0001EEB63 /* MultilevelMenuView.swift */; };
27 | 4993E84622FD57B0001EEB63 /* MultilevelMenuStyle2View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83C22FD57B0001EEB63 /* MultilevelMenuStyle2View.swift */; };
28 | 4993E84722FD57B0001EEB63 /* MultilevelStlyeMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83D22FD57B0001EEB63 /* MultilevelStlyeMenu.swift */; };
29 | 4993E84822FD57B0001EEB63 /* MultilevelStyle1Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E83E22FD57B0001EEB63 /* MultilevelStyle1Menu.swift */; };
30 | /* End PBXBuildFile section */
31 |
32 | /* Begin PBXContainerItemProxy section */
33 | 499C67182092C49200C36F75 /* PBXContainerItemProxy */ = {
34 | isa = PBXContainerItemProxy;
35 | containerPortal = 499C66FB2092C48B00C36F75 /* Project object */;
36 | proxyType = 1;
37 | remoteGlobalIDString = 499C67022092C48B00C36F75;
38 | remoteInfo = MultilevelMenuDemo;
39 | };
40 | 499C67232092C49200C36F75 /* PBXContainerItemProxy */ = {
41 | isa = PBXContainerItemProxy;
42 | containerPortal = 499C66FB2092C48B00C36F75 /* Project object */;
43 | proxyType = 1;
44 | remoteGlobalIDString = 499C67022092C48B00C36F75;
45 | remoteInfo = MultilevelMenuDemo;
46 | };
47 | /* End PBXContainerItemProxy section */
48 |
49 | /* Begin PBXFileReference section */
50 | 4993E80E22FD5753001EEB63 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
51 | 4993E81222FD5753001EEB63 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
52 | 4993E81522FD5753001EEB63 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = LaunchScreen.storyboard; sourceTree = ""; };
53 | 4993E81722FD5753001EEB63 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Main.storyboard; sourceTree = ""; };
54 | 4993E81822FD5753001EEB63 /* businessType.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = businessType.json; sourceTree = ""; };
55 | 4993E81922FD5753001EEB63 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
56 | 4993E81B22FD5754001EEB63 /* China.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = China.png; sourceTree = ""; };
57 | 4993E81C22FD5754001EEB63 /* CustomCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CustomCell.xib; sourceTree = ""; };
58 | 4993E81D22FD5754001EEB63 /* CustomCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCell.swift; sourceTree = ""; };
59 | 4993E81E22FD5754001EEB63 /* CustomMenuView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomMenuView.swift; sourceTree = ""; };
60 | 4993E81F22FD5754001EEB63 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
61 | 4993E83422FD57B0001EEB63 /* MultilevelMenuBundle.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MultilevelMenuBundle.bundle; sourceTree = ""; };
62 | 4993E83622FD57B0001EEB63 /* MenuDataModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuDataModel.swift; sourceTree = ""; };
63 | 4993E83722FD57B0001EEB63 /* MultilevelMenuOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuOption.swift; sourceTree = ""; };
64 | 4993E83822FD57B0001EEB63 /* MultilevelStyle2Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelStyle2Menu.swift; sourceTree = ""; };
65 | 4993E83922FD57B0001EEB63 /* MenuMarco.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuMarco.swift; sourceTree = ""; };
66 | 4993E83A22FD57B0001EEB63 /* MultilevelMenuStyle1View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuStyle1View.swift; sourceTree = ""; };
67 | 4993E83B22FD57B0001EEB63 /* MultilevelMenuView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuView.swift; sourceTree = ""; };
68 | 4993E83C22FD57B0001EEB63 /* MultilevelMenuStyle2View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuStyle2View.swift; sourceTree = ""; };
69 | 4993E83D22FD57B0001EEB63 /* MultilevelStlyeMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelStlyeMenu.swift; sourceTree = ""; };
70 | 4993E83E22FD57B0001EEB63 /* MultilevelStyle1Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelStyle1Menu.swift; sourceTree = ""; };
71 | 499C67032092C48B00C36F75 /* MultilevelMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MultilevelMenu.app; sourceTree = BUILT_PRODUCTS_DIR; };
72 | 499C67172092C49200C36F75 /* MultilevelMenuTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MultilevelMenuTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
73 | 499C67222092C49200C36F75 /* MultilevelMenuUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MultilevelMenuUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
74 | /* End PBXFileReference section */
75 |
76 | /* Begin PBXFrameworksBuildPhase section */
77 | 499C67002092C48B00C36F75 /* Frameworks */ = {
78 | isa = PBXFrameworksBuildPhase;
79 | buildActionMask = 2147483647;
80 | files = (
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | 499C67142092C49200C36F75 /* Frameworks */ = {
85 | isa = PBXFrameworksBuildPhase;
86 | buildActionMask = 2147483647;
87 | files = (
88 | );
89 | runOnlyForDeploymentPostprocessing = 0;
90 | };
91 | 499C671F2092C49200C36F75 /* Frameworks */ = {
92 | isa = PBXFrameworksBuildPhase;
93 | buildActionMask = 2147483647;
94 | files = (
95 | );
96 | runOnlyForDeploymentPostprocessing = 0;
97 | };
98 | /* End PBXFrameworksBuildPhase section */
99 |
100 | /* Begin PBXGroup section */
101 | 4993E81322FD5753001EEB63 /* Base.lproj */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 4993E81422FD5753001EEB63 /* LaunchScreen.storyboard */,
105 | 4993E81622FD5753001EEB63 /* Main.storyboard */,
106 | );
107 | path = Base.lproj;
108 | sourceTree = "";
109 | };
110 | 4993E81A22FD5754001EEB63 /* CustomMenu */ = {
111 | isa = PBXGroup;
112 | children = (
113 | 4993E81B22FD5754001EEB63 /* China.png */,
114 | 4993E81C22FD5754001EEB63 /* CustomCell.xib */,
115 | 4993E81D22FD5754001EEB63 /* CustomCell.swift */,
116 | 4993E81E22FD5754001EEB63 /* CustomMenuView.swift */,
117 | );
118 | path = CustomMenu;
119 | sourceTree = "";
120 | };
121 | 4993E83222FD57B0001EEB63 /* MultilevelMenu */ = {
122 | isa = PBXGroup;
123 | children = (
124 | 4993E83322FD57B0001EEB63 /* Resources */,
125 | 4993E83522FD57B0001EEB63 /* Source */,
126 | );
127 | name = MultilevelMenu;
128 | path = ../../MultilevelMenu;
129 | sourceTree = "";
130 | };
131 | 4993E83322FD57B0001EEB63 /* Resources */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 4993E83422FD57B0001EEB63 /* MultilevelMenuBundle.bundle */,
135 | );
136 | path = Resources;
137 | sourceTree = "";
138 | };
139 | 4993E83522FD57B0001EEB63 /* Source */ = {
140 | isa = PBXGroup;
141 | children = (
142 | 4993E83622FD57B0001EEB63 /* MenuDataModel.swift */,
143 | 4993E83722FD57B0001EEB63 /* MultilevelMenuOption.swift */,
144 | 4993E83822FD57B0001EEB63 /* MultilevelStyle2Menu.swift */,
145 | 4993E83922FD57B0001EEB63 /* MenuMarco.swift */,
146 | 4993E83A22FD57B0001EEB63 /* MultilevelMenuStyle1View.swift */,
147 | 4993E83B22FD57B0001EEB63 /* MultilevelMenuView.swift */,
148 | 4993E83C22FD57B0001EEB63 /* MultilevelMenuStyle2View.swift */,
149 | 4993E83D22FD57B0001EEB63 /* MultilevelStlyeMenu.swift */,
150 | 4993E83E22FD57B0001EEB63 /* MultilevelStyle1Menu.swift */,
151 | );
152 | path = Source;
153 | sourceTree = "";
154 | };
155 | 499C66FA2092C48B00C36F75 = {
156 | isa = PBXGroup;
157 | children = (
158 | 4993E83222FD57B0001EEB63 /* MultilevelMenu */,
159 | 4993E81A22FD5754001EEB63 /* CustomMenu */,
160 | 4993E80E22FD5753001EEB63 /* ViewController.swift */,
161 | 4993E81F22FD5754001EEB63 /* AppDelegate.swift */,
162 | 4993E81922FD5753001EEB63 /* Assets.xcassets */,
163 | 4993E81322FD5753001EEB63 /* Base.lproj */,
164 | 4993E81822FD5753001EEB63 /* businessType.json */,
165 | 4993E81222FD5753001EEB63 /* Info.plist */,
166 | 499C67042092C48B00C36F75 /* Products */,
167 | );
168 | sourceTree = "";
169 | };
170 | 499C67042092C48B00C36F75 /* Products */ = {
171 | isa = PBXGroup;
172 | children = (
173 | 499C67032092C48B00C36F75 /* MultilevelMenu.app */,
174 | 499C67172092C49200C36F75 /* MultilevelMenuTests.xctest */,
175 | 499C67222092C49200C36F75 /* MultilevelMenuUITests.xctest */,
176 | );
177 | name = Products;
178 | sourceTree = "";
179 | };
180 | /* End PBXGroup section */
181 |
182 | /* Begin PBXNativeTarget section */
183 | 499C67022092C48B00C36F75 /* MultilevelMenu */ = {
184 | isa = PBXNativeTarget;
185 | buildConfigurationList = 499C672B2092C49200C36F75 /* Build configuration list for PBXNativeTarget "MultilevelMenu" */;
186 | buildPhases = (
187 | 499C66FF2092C48B00C36F75 /* Sources */,
188 | 499C67002092C48B00C36F75 /* Frameworks */,
189 | 499C67012092C48B00C36F75 /* Resources */,
190 | );
191 | buildRules = (
192 | );
193 | dependencies = (
194 | );
195 | name = MultilevelMenu;
196 | productName = MultilevelMenuDemo;
197 | productReference = 499C67032092C48B00C36F75 /* MultilevelMenu.app */;
198 | productType = "com.apple.product-type.application";
199 | };
200 | 499C67162092C49200C36F75 /* MultilevelMenuTests */ = {
201 | isa = PBXNativeTarget;
202 | buildConfigurationList = 499C672E2092C49200C36F75 /* Build configuration list for PBXNativeTarget "MultilevelMenuTests" */;
203 | buildPhases = (
204 | 499C67132092C49200C36F75 /* Sources */,
205 | 499C67142092C49200C36F75 /* Frameworks */,
206 | 499C67152092C49200C36F75 /* Resources */,
207 | );
208 | buildRules = (
209 | );
210 | dependencies = (
211 | 499C67192092C49200C36F75 /* PBXTargetDependency */,
212 | );
213 | name = MultilevelMenuTests;
214 | productName = MultilevelMenuDemoTests;
215 | productReference = 499C67172092C49200C36F75 /* MultilevelMenuTests.xctest */;
216 | productType = "com.apple.product-type.bundle.unit-test";
217 | };
218 | 499C67212092C49200C36F75 /* MultilevelMenuUITests */ = {
219 | isa = PBXNativeTarget;
220 | buildConfigurationList = 499C67312092C49200C36F75 /* Build configuration list for PBXNativeTarget "MultilevelMenuUITests" */;
221 | buildPhases = (
222 | 499C671E2092C49200C36F75 /* Sources */,
223 | 499C671F2092C49200C36F75 /* Frameworks */,
224 | 499C67202092C49200C36F75 /* Resources */,
225 | );
226 | buildRules = (
227 | );
228 | dependencies = (
229 | 499C67242092C49200C36F75 /* PBXTargetDependency */,
230 | );
231 | name = MultilevelMenuUITests;
232 | productName = MultilevelMenuDemoUITests;
233 | productReference = 499C67222092C49200C36F75 /* MultilevelMenuUITests.xctest */;
234 | productType = "com.apple.product-type.bundle.ui-testing";
235 | };
236 | /* End PBXNativeTarget section */
237 |
238 | /* Begin PBXProject section */
239 | 499C66FB2092C48B00C36F75 /* Project object */ = {
240 | isa = PBXProject;
241 | attributes = {
242 | LastSwiftUpdateCheck = 0930;
243 | LastUpgradeCheck = 0930;
244 | ORGANIZATIONNAME = ChokShen;
245 | TargetAttributes = {
246 | 499C67022092C48B00C36F75 = {
247 | CreatedOnToolsVersion = 9.3;
248 | LastSwiftMigration = 1010;
249 | };
250 | 499C67162092C49200C36F75 = {
251 | CreatedOnToolsVersion = 9.3;
252 | TestTargetID = 499C67022092C48B00C36F75;
253 | };
254 | 499C67212092C49200C36F75 = {
255 | CreatedOnToolsVersion = 9.3;
256 | TestTargetID = 499C67022092C48B00C36F75;
257 | };
258 | };
259 | };
260 | buildConfigurationList = 499C66FE2092C48B00C36F75 /* Build configuration list for PBXProject "MultilevelMenu" */;
261 | compatibilityVersion = "Xcode 9.3";
262 | developmentRegion = en;
263 | hasScannedForEncodings = 0;
264 | knownRegions = (
265 | en,
266 | Base,
267 | );
268 | mainGroup = 499C66FA2092C48B00C36F75;
269 | productRefGroup = 499C67042092C48B00C36F75 /* Products */;
270 | projectDirPath = "";
271 | projectRoot = "";
272 | targets = (
273 | 499C67022092C48B00C36F75 /* MultilevelMenu */,
274 | 499C67162092C49200C36F75 /* MultilevelMenuTests */,
275 | 499C67212092C49200C36F75 /* MultilevelMenuUITests */,
276 | );
277 | };
278 | /* End PBXProject section */
279 |
280 | /* Begin PBXResourcesBuildPhase section */
281 | 499C67012092C48B00C36F75 /* Resources */ = {
282 | isa = PBXResourcesBuildPhase;
283 | buildActionMask = 2147483647;
284 | files = (
285 | 4993E82722FD5754001EEB63 /* LaunchScreen.storyboard in Resources */,
286 | 4993E82C22FD5754001EEB63 /* CustomCell.xib in Resources */,
287 | 4993E82922FD5754001EEB63 /* businessType.json in Resources */,
288 | 4993E82B22FD5754001EEB63 /* China.png in Resources */,
289 | 4993E82A22FD5754001EEB63 /* Assets.xcassets in Resources */,
290 | 4993E83F22FD57B0001EEB63 /* MultilevelMenuBundle.bundle in Resources */,
291 | 4993E82822FD5754001EEB63 /* Main.storyboard in Resources */,
292 | );
293 | runOnlyForDeploymentPostprocessing = 0;
294 | };
295 | 499C67152092C49200C36F75 /* Resources */ = {
296 | isa = PBXResourcesBuildPhase;
297 | buildActionMask = 2147483647;
298 | files = (
299 | );
300 | runOnlyForDeploymentPostprocessing = 0;
301 | };
302 | 499C67202092C49200C36F75 /* Resources */ = {
303 | isa = PBXResourcesBuildPhase;
304 | buildActionMask = 2147483647;
305 | files = (
306 | );
307 | runOnlyForDeploymentPostprocessing = 0;
308 | };
309 | /* End PBXResourcesBuildPhase section */
310 |
311 | /* Begin PBXSourcesBuildPhase section */
312 | 499C66FF2092C48B00C36F75 /* Sources */ = {
313 | isa = PBXSourcesBuildPhase;
314 | buildActionMask = 2147483647;
315 | files = (
316 | 4993E84222FD57B0001EEB63 /* MultilevelStyle2Menu.swift in Sources */,
317 | 4993E84322FD57B0001EEB63 /* MenuMarco.swift in Sources */,
318 | 4993E84122FD57B0001EEB63 /* MultilevelMenuOption.swift in Sources */,
319 | 4993E84622FD57B0001EEB63 /* MultilevelMenuStyle2View.swift in Sources */,
320 | 4993E82322FD5754001EEB63 /* ViewController.swift in Sources */,
321 | 4993E82D22FD5754001EEB63 /* CustomCell.swift in Sources */,
322 | 4993E84522FD57B0001EEB63 /* MultilevelMenuView.swift in Sources */,
323 | 4993E84722FD57B0001EEB63 /* MultilevelStlyeMenu.swift in Sources */,
324 | 4993E82E22FD5754001EEB63 /* CustomMenuView.swift in Sources */,
325 | 4993E84822FD57B0001EEB63 /* MultilevelStyle1Menu.swift in Sources */,
326 | 4993E84022FD57B0001EEB63 /* MenuDataModel.swift in Sources */,
327 | 4993E84422FD57B0001EEB63 /* MultilevelMenuStyle1View.swift in Sources */,
328 | 4993E82F22FD5754001EEB63 /* AppDelegate.swift in Sources */,
329 | );
330 | runOnlyForDeploymentPostprocessing = 0;
331 | };
332 | 499C67132092C49200C36F75 /* Sources */ = {
333 | isa = PBXSourcesBuildPhase;
334 | buildActionMask = 2147483647;
335 | files = (
336 | );
337 | runOnlyForDeploymentPostprocessing = 0;
338 | };
339 | 499C671E2092C49200C36F75 /* Sources */ = {
340 | isa = PBXSourcesBuildPhase;
341 | buildActionMask = 2147483647;
342 | files = (
343 | );
344 | runOnlyForDeploymentPostprocessing = 0;
345 | };
346 | /* End PBXSourcesBuildPhase section */
347 |
348 | /* Begin PBXTargetDependency section */
349 | 499C67192092C49200C36F75 /* PBXTargetDependency */ = {
350 | isa = PBXTargetDependency;
351 | target = 499C67022092C48B00C36F75 /* MultilevelMenu */;
352 | targetProxy = 499C67182092C49200C36F75 /* PBXContainerItemProxy */;
353 | };
354 | 499C67242092C49200C36F75 /* PBXTargetDependency */ = {
355 | isa = PBXTargetDependency;
356 | target = 499C67022092C48B00C36F75 /* MultilevelMenu */;
357 | targetProxy = 499C67232092C49200C36F75 /* PBXContainerItemProxy */;
358 | };
359 | /* End PBXTargetDependency section */
360 |
361 | /* Begin PBXVariantGroup section */
362 | 4993E81422FD5753001EEB63 /* LaunchScreen.storyboard */ = {
363 | isa = PBXVariantGroup;
364 | children = (
365 | 4993E81522FD5753001EEB63 /* Base */,
366 | );
367 | name = LaunchScreen.storyboard;
368 | sourceTree = "";
369 | };
370 | 4993E81622FD5753001EEB63 /* Main.storyboard */ = {
371 | isa = PBXVariantGroup;
372 | children = (
373 | 4993E81722FD5753001EEB63 /* Base */,
374 | );
375 | name = Main.storyboard;
376 | sourceTree = "";
377 | };
378 | /* End PBXVariantGroup section */
379 |
380 | /* Begin XCBuildConfiguration section */
381 | 499C67292092C49200C36F75 /* Debug */ = {
382 | isa = XCBuildConfiguration;
383 | buildSettings = {
384 | ALWAYS_SEARCH_USER_PATHS = NO;
385 | CLANG_ANALYZER_NONNULL = YES;
386 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
387 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
388 | CLANG_CXX_LIBRARY = "libc++";
389 | CLANG_ENABLE_MODULES = YES;
390 | CLANG_ENABLE_OBJC_ARC = YES;
391 | CLANG_ENABLE_OBJC_WEAK = YES;
392 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
393 | CLANG_WARN_BOOL_CONVERSION = YES;
394 | CLANG_WARN_COMMA = YES;
395 | CLANG_WARN_CONSTANT_CONVERSION = YES;
396 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
397 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
398 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
399 | CLANG_WARN_EMPTY_BODY = YES;
400 | CLANG_WARN_ENUM_CONVERSION = YES;
401 | CLANG_WARN_INFINITE_RECURSION = YES;
402 | CLANG_WARN_INT_CONVERSION = YES;
403 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
404 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
405 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
406 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
407 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
408 | CLANG_WARN_STRICT_PROTOTYPES = YES;
409 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
410 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
411 | CLANG_WARN_UNREACHABLE_CODE = YES;
412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
413 | CODE_SIGN_IDENTITY = "iPhone Developer";
414 | COPY_PHASE_STRIP = NO;
415 | DEBUG_INFORMATION_FORMAT = dwarf;
416 | ENABLE_STRICT_OBJC_MSGSEND = YES;
417 | ENABLE_TESTABILITY = YES;
418 | GCC_C_LANGUAGE_STANDARD = gnu11;
419 | GCC_DYNAMIC_NO_PIC = NO;
420 | GCC_NO_COMMON_BLOCKS = YES;
421 | GCC_OPTIMIZATION_LEVEL = 0;
422 | GCC_PREPROCESSOR_DEFINITIONS = (
423 | "DEBUG=1",
424 | "$(inherited)",
425 | );
426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
428 | GCC_WARN_UNDECLARED_SELECTOR = YES;
429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
430 | GCC_WARN_UNUSED_FUNCTION = YES;
431 | GCC_WARN_UNUSED_VARIABLE = YES;
432 | IPHONEOS_DEPLOYMENT_TARGET = 11.3;
433 | MTL_ENABLE_DEBUG_INFO = YES;
434 | ONLY_ACTIVE_ARCH = YES;
435 | SDKROOT = iphoneos;
436 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
437 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
438 | };
439 | name = Debug;
440 | };
441 | 499C672A2092C49200C36F75 /* Release */ = {
442 | isa = XCBuildConfiguration;
443 | buildSettings = {
444 | ALWAYS_SEARCH_USER_PATHS = NO;
445 | CLANG_ANALYZER_NONNULL = YES;
446 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
447 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
448 | CLANG_CXX_LIBRARY = "libc++";
449 | CLANG_ENABLE_MODULES = YES;
450 | CLANG_ENABLE_OBJC_ARC = YES;
451 | CLANG_ENABLE_OBJC_WEAK = YES;
452 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
453 | CLANG_WARN_BOOL_CONVERSION = YES;
454 | CLANG_WARN_COMMA = YES;
455 | CLANG_WARN_CONSTANT_CONVERSION = YES;
456 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
457 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
458 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
459 | CLANG_WARN_EMPTY_BODY = YES;
460 | CLANG_WARN_ENUM_CONVERSION = YES;
461 | CLANG_WARN_INFINITE_RECURSION = YES;
462 | CLANG_WARN_INT_CONVERSION = YES;
463 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
464 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
465 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
466 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
467 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
468 | CLANG_WARN_STRICT_PROTOTYPES = YES;
469 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
470 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
471 | CLANG_WARN_UNREACHABLE_CODE = YES;
472 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
473 | CODE_SIGN_IDENTITY = "iPhone Developer";
474 | COPY_PHASE_STRIP = NO;
475 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
476 | ENABLE_NS_ASSERTIONS = NO;
477 | ENABLE_STRICT_OBJC_MSGSEND = YES;
478 | GCC_C_LANGUAGE_STANDARD = gnu11;
479 | GCC_NO_COMMON_BLOCKS = YES;
480 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
481 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
482 | GCC_WARN_UNDECLARED_SELECTOR = YES;
483 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
484 | GCC_WARN_UNUSED_FUNCTION = YES;
485 | GCC_WARN_UNUSED_VARIABLE = YES;
486 | IPHONEOS_DEPLOYMENT_TARGET = 11.3;
487 | MTL_ENABLE_DEBUG_INFO = NO;
488 | SDKROOT = iphoneos;
489 | SWIFT_COMPILATION_MODE = wholemodule;
490 | SWIFT_OPTIMIZATION_LEVEL = "-O";
491 | VALIDATE_PRODUCT = YES;
492 | };
493 | name = Release;
494 | };
495 | 499C672C2092C49200C36F75 /* Debug */ = {
496 | isa = XCBuildConfiguration;
497 | buildSettings = {
498 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
499 | CLANG_ENABLE_MODULES = YES;
500 | CODE_SIGN_STYLE = Automatic;
501 | DEVELOPMENT_TEAM = RJUJXP82S4;
502 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
503 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
504 | LD_RUNPATH_SEARCH_PATHS = (
505 | "$(inherited)",
506 | "@executable_path/Frameworks",
507 | );
508 | PRODUCT_BUNDLE_IDENTIFIER = com.ChokShen.MultilevelMenuDemo;
509 | PRODUCT_NAME = "$(TARGET_NAME)";
510 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
511 | SWIFT_VERSION = 5.0;
512 | TARGETED_DEVICE_FAMILY = "1,2";
513 | };
514 | name = Debug;
515 | };
516 | 499C672D2092C49200C36F75 /* Release */ = {
517 | isa = XCBuildConfiguration;
518 | buildSettings = {
519 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
520 | CLANG_ENABLE_MODULES = YES;
521 | CODE_SIGN_STYLE = Automatic;
522 | DEVELOPMENT_TEAM = RJUJXP82S4;
523 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
524 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
525 | LD_RUNPATH_SEARCH_PATHS = (
526 | "$(inherited)",
527 | "@executable_path/Frameworks",
528 | );
529 | PRODUCT_BUNDLE_IDENTIFIER = com.ChokShen.MultilevelMenuDemo;
530 | PRODUCT_NAME = "$(TARGET_NAME)";
531 | SWIFT_VERSION = 5.0;
532 | TARGETED_DEVICE_FAMILY = "1,2";
533 | };
534 | name = Release;
535 | };
536 | 499C672F2092C49200C36F75 /* Debug */ = {
537 | isa = XCBuildConfiguration;
538 | buildSettings = {
539 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
540 | BUNDLE_LOADER = "$(TEST_HOST)";
541 | CODE_SIGN_STYLE = Automatic;
542 | INFOPLIST_FILE = MultilevelMenuDemoTests/Info.plist;
543 | LD_RUNPATH_SEARCH_PATHS = (
544 | "$(inherited)",
545 | "@executable_path/Frameworks",
546 | "@loader_path/Frameworks",
547 | );
548 | PRODUCT_BUNDLE_IDENTIFIER = com.ChokShen.MultilevelMenuDemoTests;
549 | PRODUCT_NAME = "$(TARGET_NAME)";
550 | SWIFT_VERSION = 4.0;
551 | TARGETED_DEVICE_FAMILY = "1,2";
552 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MultilevelMenu.app/MultilevelMenu";
553 | };
554 | name = Debug;
555 | };
556 | 499C67302092C49200C36F75 /* Release */ = {
557 | isa = XCBuildConfiguration;
558 | buildSettings = {
559 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
560 | BUNDLE_LOADER = "$(TEST_HOST)";
561 | CODE_SIGN_STYLE = Automatic;
562 | INFOPLIST_FILE = MultilevelMenuDemoTests/Info.plist;
563 | LD_RUNPATH_SEARCH_PATHS = (
564 | "$(inherited)",
565 | "@executable_path/Frameworks",
566 | "@loader_path/Frameworks",
567 | );
568 | PRODUCT_BUNDLE_IDENTIFIER = com.ChokShen.MultilevelMenuDemoTests;
569 | PRODUCT_NAME = "$(TARGET_NAME)";
570 | SWIFT_VERSION = 4.0;
571 | TARGETED_DEVICE_FAMILY = "1,2";
572 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MultilevelMenu.app/MultilevelMenu";
573 | };
574 | name = Release;
575 | };
576 | 499C67322092C49200C36F75 /* Debug */ = {
577 | isa = XCBuildConfiguration;
578 | buildSettings = {
579 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
580 | CODE_SIGN_STYLE = Automatic;
581 | INFOPLIST_FILE = MultilevelMenuDemoUITests/Info.plist;
582 | LD_RUNPATH_SEARCH_PATHS = (
583 | "$(inherited)",
584 | "@executable_path/Frameworks",
585 | "@loader_path/Frameworks",
586 | );
587 | PRODUCT_BUNDLE_IDENTIFIER = com.ChokShen.MultilevelMenuDemoUITests;
588 | PRODUCT_NAME = "$(TARGET_NAME)";
589 | SWIFT_VERSION = 4.0;
590 | TARGETED_DEVICE_FAMILY = "1,2";
591 | TEST_TARGET_NAME = MultilevelMenuDemo;
592 | };
593 | name = Debug;
594 | };
595 | 499C67332092C49200C36F75 /* Release */ = {
596 | isa = XCBuildConfiguration;
597 | buildSettings = {
598 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
599 | CODE_SIGN_STYLE = Automatic;
600 | INFOPLIST_FILE = MultilevelMenuDemoUITests/Info.plist;
601 | LD_RUNPATH_SEARCH_PATHS = (
602 | "$(inherited)",
603 | "@executable_path/Frameworks",
604 | "@loader_path/Frameworks",
605 | );
606 | PRODUCT_BUNDLE_IDENTIFIER = com.ChokShen.MultilevelMenuDemoUITests;
607 | PRODUCT_NAME = "$(TARGET_NAME)";
608 | SWIFT_VERSION = 4.0;
609 | TARGETED_DEVICE_FAMILY = "1,2";
610 | TEST_TARGET_NAME = MultilevelMenuDemo;
611 | };
612 | name = Release;
613 | };
614 | /* End XCBuildConfiguration section */
615 |
616 | /* Begin XCConfigurationList section */
617 | 499C66FE2092C48B00C36F75 /* Build configuration list for PBXProject "MultilevelMenu" */ = {
618 | isa = XCConfigurationList;
619 | buildConfigurations = (
620 | 499C67292092C49200C36F75 /* Debug */,
621 | 499C672A2092C49200C36F75 /* Release */,
622 | );
623 | defaultConfigurationIsVisible = 0;
624 | defaultConfigurationName = Release;
625 | };
626 | 499C672B2092C49200C36F75 /* Build configuration list for PBXNativeTarget "MultilevelMenu" */ = {
627 | isa = XCConfigurationList;
628 | buildConfigurations = (
629 | 499C672C2092C49200C36F75 /* Debug */,
630 | 499C672D2092C49200C36F75 /* Release */,
631 | );
632 | defaultConfigurationIsVisible = 0;
633 | defaultConfigurationName = Release;
634 | };
635 | 499C672E2092C49200C36F75 /* Build configuration list for PBXNativeTarget "MultilevelMenuTests" */ = {
636 | isa = XCConfigurationList;
637 | buildConfigurations = (
638 | 499C672F2092C49200C36F75 /* Debug */,
639 | 499C67302092C49200C36F75 /* Release */,
640 | );
641 | defaultConfigurationIsVisible = 0;
642 | defaultConfigurationName = Release;
643 | };
644 | 499C67312092C49200C36F75 /* Build configuration list for PBXNativeTarget "MultilevelMenuUITests" */ = {
645 | isa = XCConfigurationList;
646 | buildConfigurations = (
647 | 499C67322092C49200C36F75 /* Debug */,
648 | 499C67332092C49200C36F75 /* Release */,
649 | );
650 | defaultConfigurationIsVisible = 0;
651 | defaultConfigurationName = Release;
652 | };
653 | /* End XCConfigurationList section */
654 | };
655 | rootObject = 499C66FB2092C48B00C36F75 /* Project object */;
656 | }
657 |
--------------------------------------------------------------------------------
/Demo/MultilevelMenuOC/MultilevelMenuOC.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4993E7DC22FD53BD001EEB63 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4993E7DB22FD53BD001EEB63 /* AppDelegate.m */; };
11 | 4993E7DF22FD53BD001EEB63 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4993E7DE22FD53BD001EEB63 /* ViewController.m */; };
12 | 4993E7E222FD53BD001EEB63 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4993E7E022FD53BD001EEB63 /* Main.storyboard */; };
13 | 4993E7E422FD53BF001EEB63 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4993E7E322FD53BF001EEB63 /* Assets.xcassets */; };
14 | 4993E7E722FD53BF001EEB63 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4993E7E522FD53BF001EEB63 /* LaunchScreen.storyboard */; };
15 | 4993E7EA22FD53BF001EEB63 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4993E7E922FD53BF001EEB63 /* main.m */; };
16 | 4993E7F422FD53BF001EEB63 /* MultilevelMenuOCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4993E7F322FD53BF001EEB63 /* MultilevelMenuOCTests.m */; };
17 | 4993E7FF22FD53BF001EEB63 /* MultilevelMenuOCUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4993E7FE22FD53BF001EEB63 /* MultilevelMenuOCUITests.m */; };
18 | 4993E85822FD5BC8001EEB63 /* MultilevelMenuBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4993E84D22FD5BC8001EEB63 /* MultilevelMenuBundle.bundle */; };
19 | 4993E85922FD5BC8001EEB63 /* MenuDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E84F22FD5BC8001EEB63 /* MenuDataModel.swift */; };
20 | 4993E85A22FD5BC8001EEB63 /* MultilevelMenuOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85022FD5BC8001EEB63 /* MultilevelMenuOption.swift */; };
21 | 4993E85B22FD5BC8001EEB63 /* MultilevelStyle2Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85122FD5BC8001EEB63 /* MultilevelStyle2Menu.swift */; };
22 | 4993E85C22FD5BC8001EEB63 /* MenuMarco.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85222FD5BC8001EEB63 /* MenuMarco.swift */; };
23 | 4993E85D22FD5BC8001EEB63 /* MultilevelMenuStyle1View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85322FD5BC8001EEB63 /* MultilevelMenuStyle1View.swift */; };
24 | 4993E85E22FD5BC8001EEB63 /* MultilevelMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85422FD5BC8001EEB63 /* MultilevelMenuView.swift */; };
25 | 4993E85F22FD5BC8001EEB63 /* MultilevelMenuStyle2View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85522FD5BC8001EEB63 /* MultilevelMenuStyle2View.swift */; };
26 | 4993E86022FD5BC8001EEB63 /* MultilevelStlyeMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85622FD5BC8001EEB63 /* MultilevelStlyeMenu.swift */; };
27 | 4993E86122FD5BC8001EEB63 /* MultilevelStyle1Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4993E85722FD5BC8001EEB63 /* MultilevelStyle1Menu.swift */; };
28 | 4993E86722FD7065001EEB63 /* businessType.json in Resources */ = {isa = PBXBuildFile; fileRef = 4993E86622FD7065001EEB63 /* businessType.json */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXContainerItemProxy section */
32 | 4993E7F022FD53BF001EEB63 /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = 4993E7CF22FD53BD001EEB63 /* Project object */;
35 | proxyType = 1;
36 | remoteGlobalIDString = 4993E7D622FD53BD001EEB63;
37 | remoteInfo = MultilevelMenuOC;
38 | };
39 | 4993E7FB22FD53BF001EEB63 /* PBXContainerItemProxy */ = {
40 | isa = PBXContainerItemProxy;
41 | containerPortal = 4993E7CF22FD53BD001EEB63 /* Project object */;
42 | proxyType = 1;
43 | remoteGlobalIDString = 4993E7D622FD53BD001EEB63;
44 | remoteInfo = MultilevelMenuOC;
45 | };
46 | /* End PBXContainerItemProxy section */
47 |
48 | /* Begin PBXFileReference section */
49 | 4993E7D722FD53BD001EEB63 /* MultilevelMenuOC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MultilevelMenuOC.app; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 4993E7DA22FD53BD001EEB63 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
51 | 4993E7DB22FD53BD001EEB63 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
52 | 4993E7DD22FD53BD001EEB63 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
53 | 4993E7DE22FD53BD001EEB63 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
54 | 4993E7E122FD53BD001EEB63 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
55 | 4993E7E322FD53BF001EEB63 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
56 | 4993E7E622FD53BF001EEB63 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
57 | 4993E7E822FD53BF001EEB63 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | 4993E7E922FD53BF001EEB63 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
59 | 4993E7EF22FD53BF001EEB63 /* MultilevelMenuOCTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MultilevelMenuOCTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
60 | 4993E7F322FD53BF001EEB63 /* MultilevelMenuOCTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MultilevelMenuOCTests.m; sourceTree = ""; };
61 | 4993E7F522FD53BF001EEB63 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
62 | 4993E7FA22FD53BF001EEB63 /* MultilevelMenuOCUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MultilevelMenuOCUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
63 | 4993E7FE22FD53BF001EEB63 /* MultilevelMenuOCUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MultilevelMenuOCUITests.m; sourceTree = ""; };
64 | 4993E80022FD53BF001EEB63 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
65 | 4993E84D22FD5BC8001EEB63 /* MultilevelMenuBundle.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MultilevelMenuBundle.bundle; sourceTree = ""; };
66 | 4993E84F22FD5BC8001EEB63 /* MenuDataModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuDataModel.swift; sourceTree = ""; };
67 | 4993E85022FD5BC8001EEB63 /* MultilevelMenuOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuOption.swift; sourceTree = ""; };
68 | 4993E85122FD5BC8001EEB63 /* MultilevelStyle2Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelStyle2Menu.swift; sourceTree = ""; };
69 | 4993E85222FD5BC8001EEB63 /* MenuMarco.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuMarco.swift; sourceTree = ""; };
70 | 4993E85322FD5BC8001EEB63 /* MultilevelMenuStyle1View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuStyle1View.swift; sourceTree = ""; };
71 | 4993E85422FD5BC8001EEB63 /* MultilevelMenuView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuView.swift; sourceTree = ""; };
72 | 4993E85522FD5BC8001EEB63 /* MultilevelMenuStyle2View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelMenuStyle2View.swift; sourceTree = ""; };
73 | 4993E85622FD5BC8001EEB63 /* MultilevelStlyeMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelStlyeMenu.swift; sourceTree = ""; };
74 | 4993E85722FD5BC8001EEB63 /* MultilevelStyle1Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilevelStyle1Menu.swift; sourceTree = ""; };
75 | 4993E86622FD7065001EEB63 /* businessType.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = businessType.json; path = ../../MultilevelMenuSwift/businessType.json; sourceTree = ""; };
76 | /* End PBXFileReference section */
77 |
78 | /* Begin PBXFrameworksBuildPhase section */
79 | 4993E7D422FD53BD001EEB63 /* Frameworks */ = {
80 | isa = PBXFrameworksBuildPhase;
81 | buildActionMask = 2147483647;
82 | files = (
83 | );
84 | runOnlyForDeploymentPostprocessing = 0;
85 | };
86 | 4993E7EC22FD53BF001EEB63 /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | );
91 | runOnlyForDeploymentPostprocessing = 0;
92 | };
93 | 4993E7F722FD53BF001EEB63 /* Frameworks */ = {
94 | isa = PBXFrameworksBuildPhase;
95 | buildActionMask = 2147483647;
96 | files = (
97 | );
98 | runOnlyForDeploymentPostprocessing = 0;
99 | };
100 | /* End PBXFrameworksBuildPhase section */
101 |
102 | /* Begin PBXGroup section */
103 | 4993E7CE22FD53BD001EEB63 = {
104 | isa = PBXGroup;
105 | children = (
106 | 4993E84B22FD5BC8001EEB63 /* MultilevelMenu */,
107 | 4993E7D922FD53BD001EEB63 /* MultilevelMenuOC */,
108 | 4993E7F222FD53BF001EEB63 /* MultilevelMenuOCTests */,
109 | 4993E7FD22FD53BF001EEB63 /* MultilevelMenuOCUITests */,
110 | 4993E7D822FD53BD001EEB63 /* Products */,
111 | );
112 | sourceTree = "";
113 | };
114 | 4993E7D822FD53BD001EEB63 /* Products */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 4993E7D722FD53BD001EEB63 /* MultilevelMenuOC.app */,
118 | 4993E7EF22FD53BF001EEB63 /* MultilevelMenuOCTests.xctest */,
119 | 4993E7FA22FD53BF001EEB63 /* MultilevelMenuOCUITests.xctest */,
120 | );
121 | name = Products;
122 | sourceTree = "";
123 | };
124 | 4993E7D922FD53BD001EEB63 /* MultilevelMenuOC */ = {
125 | isa = PBXGroup;
126 | children = (
127 | 4993E86622FD7065001EEB63 /* businessType.json */,
128 | 4993E7DA22FD53BD001EEB63 /* AppDelegate.h */,
129 | 4993E7DB22FD53BD001EEB63 /* AppDelegate.m */,
130 | 4993E7DD22FD53BD001EEB63 /* ViewController.h */,
131 | 4993E7DE22FD53BD001EEB63 /* ViewController.m */,
132 | 4993E7E022FD53BD001EEB63 /* Main.storyboard */,
133 | 4993E7E322FD53BF001EEB63 /* Assets.xcassets */,
134 | 4993E7E522FD53BF001EEB63 /* LaunchScreen.storyboard */,
135 | 4993E7E822FD53BF001EEB63 /* Info.plist */,
136 | 4993E7E922FD53BF001EEB63 /* main.m */,
137 | );
138 | path = MultilevelMenuOC;
139 | sourceTree = "";
140 | };
141 | 4993E7F222FD53BF001EEB63 /* MultilevelMenuOCTests */ = {
142 | isa = PBXGroup;
143 | children = (
144 | 4993E7F322FD53BF001EEB63 /* MultilevelMenuOCTests.m */,
145 | 4993E7F522FD53BF001EEB63 /* Info.plist */,
146 | );
147 | path = MultilevelMenuOCTests;
148 | sourceTree = "";
149 | };
150 | 4993E7FD22FD53BF001EEB63 /* MultilevelMenuOCUITests */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 4993E7FE22FD53BF001EEB63 /* MultilevelMenuOCUITests.m */,
154 | 4993E80022FD53BF001EEB63 /* Info.plist */,
155 | );
156 | path = MultilevelMenuOCUITests;
157 | sourceTree = "";
158 | };
159 | 4993E84B22FD5BC8001EEB63 /* MultilevelMenu */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 4993E84C22FD5BC8001EEB63 /* Resources */,
163 | 4993E84E22FD5BC8001EEB63 /* Source */,
164 | );
165 | name = MultilevelMenu;
166 | path = ../../MultilevelMenu;
167 | sourceTree = "";
168 | };
169 | 4993E84C22FD5BC8001EEB63 /* Resources */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 4993E84D22FD5BC8001EEB63 /* MultilevelMenuBundle.bundle */,
173 | );
174 | path = Resources;
175 | sourceTree = "";
176 | };
177 | 4993E84E22FD5BC8001EEB63 /* Source */ = {
178 | isa = PBXGroup;
179 | children = (
180 | 4993E84F22FD5BC8001EEB63 /* MenuDataModel.swift */,
181 | 4993E85022FD5BC8001EEB63 /* MultilevelMenuOption.swift */,
182 | 4993E85122FD5BC8001EEB63 /* MultilevelStyle2Menu.swift */,
183 | 4993E85222FD5BC8001EEB63 /* MenuMarco.swift */,
184 | 4993E85322FD5BC8001EEB63 /* MultilevelMenuStyle1View.swift */,
185 | 4993E85422FD5BC8001EEB63 /* MultilevelMenuView.swift */,
186 | 4993E85522FD5BC8001EEB63 /* MultilevelMenuStyle2View.swift */,
187 | 4993E85622FD5BC8001EEB63 /* MultilevelStlyeMenu.swift */,
188 | 4993E85722FD5BC8001EEB63 /* MultilevelStyle1Menu.swift */,
189 | );
190 | path = Source;
191 | sourceTree = "";
192 | };
193 | /* End PBXGroup section */
194 |
195 | /* Begin PBXNativeTarget section */
196 | 4993E7D622FD53BD001EEB63 /* MultilevelMenuOC */ = {
197 | isa = PBXNativeTarget;
198 | buildConfigurationList = 4993E80322FD53BF001EEB63 /* Build configuration list for PBXNativeTarget "MultilevelMenuOC" */;
199 | buildPhases = (
200 | 4993E7D322FD53BD001EEB63 /* Sources */,
201 | 4993E7D422FD53BD001EEB63 /* Frameworks */,
202 | 4993E7D522FD53BD001EEB63 /* Resources */,
203 | );
204 | buildRules = (
205 | );
206 | dependencies = (
207 | );
208 | name = MultilevelMenuOC;
209 | productName = MultilevelMenuOC;
210 | productReference = 4993E7D722FD53BD001EEB63 /* MultilevelMenuOC.app */;
211 | productType = "com.apple.product-type.application";
212 | };
213 | 4993E7EE22FD53BF001EEB63 /* MultilevelMenuOCTests */ = {
214 | isa = PBXNativeTarget;
215 | buildConfigurationList = 4993E80622FD53BF001EEB63 /* Build configuration list for PBXNativeTarget "MultilevelMenuOCTests" */;
216 | buildPhases = (
217 | 4993E7EB22FD53BF001EEB63 /* Sources */,
218 | 4993E7EC22FD53BF001EEB63 /* Frameworks */,
219 | 4993E7ED22FD53BF001EEB63 /* Resources */,
220 | );
221 | buildRules = (
222 | );
223 | dependencies = (
224 | 4993E7F122FD53BF001EEB63 /* PBXTargetDependency */,
225 | );
226 | name = MultilevelMenuOCTests;
227 | productName = MultilevelMenuOCTests;
228 | productReference = 4993E7EF22FD53BF001EEB63 /* MultilevelMenuOCTests.xctest */;
229 | productType = "com.apple.product-type.bundle.unit-test";
230 | };
231 | 4993E7F922FD53BF001EEB63 /* MultilevelMenuOCUITests */ = {
232 | isa = PBXNativeTarget;
233 | buildConfigurationList = 4993E80922FD53BF001EEB63 /* Build configuration list for PBXNativeTarget "MultilevelMenuOCUITests" */;
234 | buildPhases = (
235 | 4993E7F622FD53BF001EEB63 /* Sources */,
236 | 4993E7F722FD53BF001EEB63 /* Frameworks */,
237 | 4993E7F822FD53BF001EEB63 /* Resources */,
238 | );
239 | buildRules = (
240 | );
241 | dependencies = (
242 | 4993E7FC22FD53BF001EEB63 /* PBXTargetDependency */,
243 | );
244 | name = MultilevelMenuOCUITests;
245 | productName = MultilevelMenuOCUITests;
246 | productReference = 4993E7FA22FD53BF001EEB63 /* MultilevelMenuOCUITests.xctest */;
247 | productType = "com.apple.product-type.bundle.ui-testing";
248 | };
249 | /* End PBXNativeTarget section */
250 |
251 | /* Begin PBXProject section */
252 | 4993E7CF22FD53BD001EEB63 /* Project object */ = {
253 | isa = PBXProject;
254 | attributes = {
255 | LastUpgradeCheck = 1010;
256 | ORGANIZATIONNAME = forwor;
257 | TargetAttributes = {
258 | 4993E7D622FD53BD001EEB63 = {
259 | CreatedOnToolsVersion = 10.1;
260 | };
261 | 4993E7EE22FD53BF001EEB63 = {
262 | CreatedOnToolsVersion = 10.1;
263 | TestTargetID = 4993E7D622FD53BD001EEB63;
264 | };
265 | 4993E7F922FD53BF001EEB63 = {
266 | CreatedOnToolsVersion = 10.1;
267 | TestTargetID = 4993E7D622FD53BD001EEB63;
268 | };
269 | };
270 | };
271 | buildConfigurationList = 4993E7D222FD53BD001EEB63 /* Build configuration list for PBXProject "MultilevelMenuOC" */;
272 | compatibilityVersion = "Xcode 9.3";
273 | developmentRegion = en;
274 | hasScannedForEncodings = 0;
275 | knownRegions = (
276 | en,
277 | Base,
278 | );
279 | mainGroup = 4993E7CE22FD53BD001EEB63;
280 | productRefGroup = 4993E7D822FD53BD001EEB63 /* Products */;
281 | projectDirPath = "";
282 | projectRoot = "";
283 | targets = (
284 | 4993E7D622FD53BD001EEB63 /* MultilevelMenuOC */,
285 | 4993E7EE22FD53BF001EEB63 /* MultilevelMenuOCTests */,
286 | 4993E7F922FD53BF001EEB63 /* MultilevelMenuOCUITests */,
287 | );
288 | };
289 | /* End PBXProject section */
290 |
291 | /* Begin PBXResourcesBuildPhase section */
292 | 4993E7D522FD53BD001EEB63 /* Resources */ = {
293 | isa = PBXResourcesBuildPhase;
294 | buildActionMask = 2147483647;
295 | files = (
296 | 4993E7E722FD53BF001EEB63 /* LaunchScreen.storyboard in Resources */,
297 | 4993E85822FD5BC8001EEB63 /* MultilevelMenuBundle.bundle in Resources */,
298 | 4993E86722FD7065001EEB63 /* businessType.json in Resources */,
299 | 4993E7E422FD53BF001EEB63 /* Assets.xcassets in Resources */,
300 | 4993E7E222FD53BD001EEB63 /* Main.storyboard in Resources */,
301 | );
302 | runOnlyForDeploymentPostprocessing = 0;
303 | };
304 | 4993E7ED22FD53BF001EEB63 /* Resources */ = {
305 | isa = PBXResourcesBuildPhase;
306 | buildActionMask = 2147483647;
307 | files = (
308 | );
309 | runOnlyForDeploymentPostprocessing = 0;
310 | };
311 | 4993E7F822FD53BF001EEB63 /* Resources */ = {
312 | isa = PBXResourcesBuildPhase;
313 | buildActionMask = 2147483647;
314 | files = (
315 | );
316 | runOnlyForDeploymentPostprocessing = 0;
317 | };
318 | /* End PBXResourcesBuildPhase section */
319 |
320 | /* Begin PBXSourcesBuildPhase section */
321 | 4993E7D322FD53BD001EEB63 /* Sources */ = {
322 | isa = PBXSourcesBuildPhase;
323 | buildActionMask = 2147483647;
324 | files = (
325 | 4993E85B22FD5BC8001EEB63 /* MultilevelStyle2Menu.swift in Sources */,
326 | 4993E85E22FD5BC8001EEB63 /* MultilevelMenuView.swift in Sources */,
327 | 4993E7DF22FD53BD001EEB63 /* ViewController.m in Sources */,
328 | 4993E7EA22FD53BF001EEB63 /* main.m in Sources */,
329 | 4993E85A22FD5BC8001EEB63 /* MultilevelMenuOption.swift in Sources */,
330 | 4993E86022FD5BC8001EEB63 /* MultilevelStlyeMenu.swift in Sources */,
331 | 4993E85F22FD5BC8001EEB63 /* MultilevelMenuStyle2View.swift in Sources */,
332 | 4993E86122FD5BC8001EEB63 /* MultilevelStyle1Menu.swift in Sources */,
333 | 4993E85922FD5BC8001EEB63 /* MenuDataModel.swift in Sources */,
334 | 4993E7DC22FD53BD001EEB63 /* AppDelegate.m in Sources */,
335 | 4993E85D22FD5BC8001EEB63 /* MultilevelMenuStyle1View.swift in Sources */,
336 | 4993E85C22FD5BC8001EEB63 /* MenuMarco.swift in Sources */,
337 | );
338 | runOnlyForDeploymentPostprocessing = 0;
339 | };
340 | 4993E7EB22FD53BF001EEB63 /* Sources */ = {
341 | isa = PBXSourcesBuildPhase;
342 | buildActionMask = 2147483647;
343 | files = (
344 | 4993E7F422FD53BF001EEB63 /* MultilevelMenuOCTests.m in Sources */,
345 | );
346 | runOnlyForDeploymentPostprocessing = 0;
347 | };
348 | 4993E7F622FD53BF001EEB63 /* Sources */ = {
349 | isa = PBXSourcesBuildPhase;
350 | buildActionMask = 2147483647;
351 | files = (
352 | 4993E7FF22FD53BF001EEB63 /* MultilevelMenuOCUITests.m in Sources */,
353 | );
354 | runOnlyForDeploymentPostprocessing = 0;
355 | };
356 | /* End PBXSourcesBuildPhase section */
357 |
358 | /* Begin PBXTargetDependency section */
359 | 4993E7F122FD53BF001EEB63 /* PBXTargetDependency */ = {
360 | isa = PBXTargetDependency;
361 | target = 4993E7D622FD53BD001EEB63 /* MultilevelMenuOC */;
362 | targetProxy = 4993E7F022FD53BF001EEB63 /* PBXContainerItemProxy */;
363 | };
364 | 4993E7FC22FD53BF001EEB63 /* PBXTargetDependency */ = {
365 | isa = PBXTargetDependency;
366 | target = 4993E7D622FD53BD001EEB63 /* MultilevelMenuOC */;
367 | targetProxy = 4993E7FB22FD53BF001EEB63 /* PBXContainerItemProxy */;
368 | };
369 | /* End PBXTargetDependency section */
370 |
371 | /* Begin PBXVariantGroup section */
372 | 4993E7E022FD53BD001EEB63 /* Main.storyboard */ = {
373 | isa = PBXVariantGroup;
374 | children = (
375 | 4993E7E122FD53BD001EEB63 /* Base */,
376 | );
377 | name = Main.storyboard;
378 | sourceTree = "";
379 | };
380 | 4993E7E522FD53BF001EEB63 /* LaunchScreen.storyboard */ = {
381 | isa = PBXVariantGroup;
382 | children = (
383 | 4993E7E622FD53BF001EEB63 /* Base */,
384 | );
385 | name = LaunchScreen.storyboard;
386 | sourceTree = "";
387 | };
388 | /* End PBXVariantGroup section */
389 |
390 | /* Begin XCBuildConfiguration section */
391 | 4993E80122FD53BF001EEB63 /* Debug */ = {
392 | isa = XCBuildConfiguration;
393 | buildSettings = {
394 | ALWAYS_SEARCH_USER_PATHS = NO;
395 | CLANG_ANALYZER_NONNULL = YES;
396 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
398 | CLANG_CXX_LIBRARY = "libc++";
399 | CLANG_ENABLE_MODULES = YES;
400 | CLANG_ENABLE_OBJC_ARC = YES;
401 | CLANG_ENABLE_OBJC_WEAK = YES;
402 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
403 | CLANG_WARN_BOOL_CONVERSION = YES;
404 | CLANG_WARN_COMMA = YES;
405 | CLANG_WARN_CONSTANT_CONVERSION = YES;
406 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
408 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
409 | CLANG_WARN_EMPTY_BODY = YES;
410 | CLANG_WARN_ENUM_CONVERSION = YES;
411 | CLANG_WARN_INFINITE_RECURSION = YES;
412 | CLANG_WARN_INT_CONVERSION = YES;
413 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
414 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
415 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
416 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
417 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
418 | CLANG_WARN_STRICT_PROTOTYPES = YES;
419 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
420 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
421 | CLANG_WARN_UNREACHABLE_CODE = YES;
422 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
423 | CODE_SIGN_IDENTITY = "iPhone Developer";
424 | COPY_PHASE_STRIP = NO;
425 | DEBUG_INFORMATION_FORMAT = dwarf;
426 | ENABLE_STRICT_OBJC_MSGSEND = YES;
427 | ENABLE_TESTABILITY = YES;
428 | GCC_C_LANGUAGE_STANDARD = gnu11;
429 | GCC_DYNAMIC_NO_PIC = NO;
430 | GCC_NO_COMMON_BLOCKS = YES;
431 | GCC_OPTIMIZATION_LEVEL = 0;
432 | GCC_PREPROCESSOR_DEFINITIONS = (
433 | "DEBUG=1",
434 | "$(inherited)",
435 | );
436 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
437 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
438 | GCC_WARN_UNDECLARED_SELECTOR = YES;
439 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
440 | GCC_WARN_UNUSED_FUNCTION = YES;
441 | GCC_WARN_UNUSED_VARIABLE = YES;
442 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
443 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
444 | MTL_FAST_MATH = YES;
445 | ONLY_ACTIVE_ARCH = YES;
446 | SDKROOT = iphoneos;
447 | };
448 | name = Debug;
449 | };
450 | 4993E80222FD53BF001EEB63 /* Release */ = {
451 | isa = XCBuildConfiguration;
452 | buildSettings = {
453 | ALWAYS_SEARCH_USER_PATHS = NO;
454 | CLANG_ANALYZER_NONNULL = YES;
455 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
456 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
457 | CLANG_CXX_LIBRARY = "libc++";
458 | CLANG_ENABLE_MODULES = YES;
459 | CLANG_ENABLE_OBJC_ARC = YES;
460 | CLANG_ENABLE_OBJC_WEAK = YES;
461 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
462 | CLANG_WARN_BOOL_CONVERSION = YES;
463 | CLANG_WARN_COMMA = YES;
464 | CLANG_WARN_CONSTANT_CONVERSION = YES;
465 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
466 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
467 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
468 | CLANG_WARN_EMPTY_BODY = YES;
469 | CLANG_WARN_ENUM_CONVERSION = YES;
470 | CLANG_WARN_INFINITE_RECURSION = YES;
471 | CLANG_WARN_INT_CONVERSION = YES;
472 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
473 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
474 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
475 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
476 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
477 | CLANG_WARN_STRICT_PROTOTYPES = YES;
478 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
479 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
480 | CLANG_WARN_UNREACHABLE_CODE = YES;
481 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
482 | CODE_SIGN_IDENTITY = "iPhone Developer";
483 | COPY_PHASE_STRIP = NO;
484 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
485 | ENABLE_NS_ASSERTIONS = NO;
486 | ENABLE_STRICT_OBJC_MSGSEND = YES;
487 | GCC_C_LANGUAGE_STANDARD = gnu11;
488 | GCC_NO_COMMON_BLOCKS = YES;
489 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
490 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
491 | GCC_WARN_UNDECLARED_SELECTOR = YES;
492 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
493 | GCC_WARN_UNUSED_FUNCTION = YES;
494 | GCC_WARN_UNUSED_VARIABLE = YES;
495 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
496 | MTL_ENABLE_DEBUG_INFO = NO;
497 | MTL_FAST_MATH = YES;
498 | SDKROOT = iphoneos;
499 | VALIDATE_PRODUCT = YES;
500 | };
501 | name = Release;
502 | };
503 | 4993E80422FD53BF001EEB63 /* Debug */ = {
504 | isa = XCBuildConfiguration;
505 | buildSettings = {
506 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
507 | CODE_SIGN_STYLE = Automatic;
508 | DEFINES_MODULE = YES;
509 | DEVELOPMENT_TEAM = RJUJXP82S4;
510 | INFOPLIST_FILE = MultilevelMenuOC/Info.plist;
511 | LD_RUNPATH_SEARCH_PATHS = (
512 | "$(inherited)",
513 | "@executable_path/Frameworks",
514 | );
515 | PRODUCT_BUNDLE_IDENTIFIER = shenzhiqiang.MultilevelMenuOC;
516 | PRODUCT_NAME = "$(TARGET_NAME)";
517 | SWIFT_OBJC_BRIDGING_HEADER = "";
518 | SWIFT_VERSION = 4.2;
519 | TARGETED_DEVICE_FAMILY = "1,2";
520 | };
521 | name = Debug;
522 | };
523 | 4993E80522FD53BF001EEB63 /* Release */ = {
524 | isa = XCBuildConfiguration;
525 | buildSettings = {
526 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
527 | CODE_SIGN_STYLE = Automatic;
528 | DEFINES_MODULE = YES;
529 | DEVELOPMENT_TEAM = RJUJXP82S4;
530 | INFOPLIST_FILE = MultilevelMenuOC/Info.plist;
531 | LD_RUNPATH_SEARCH_PATHS = (
532 | "$(inherited)",
533 | "@executable_path/Frameworks",
534 | );
535 | PRODUCT_BUNDLE_IDENTIFIER = shenzhiqiang.MultilevelMenuOC;
536 | PRODUCT_NAME = "$(TARGET_NAME)";
537 | SWIFT_OBJC_BRIDGING_HEADER = "";
538 | SWIFT_VERSION = 4.2;
539 | TARGETED_DEVICE_FAMILY = "1,2";
540 | };
541 | name = Release;
542 | };
543 | 4993E80722FD53BF001EEB63 /* Debug */ = {
544 | isa = XCBuildConfiguration;
545 | buildSettings = {
546 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
547 | BUNDLE_LOADER = "$(TEST_HOST)";
548 | CODE_SIGN_STYLE = Automatic;
549 | DEVELOPMENT_TEAM = RJUJXP82S4;
550 | INFOPLIST_FILE = MultilevelMenuOCTests/Info.plist;
551 | LD_RUNPATH_SEARCH_PATHS = (
552 | "$(inherited)",
553 | "@executable_path/Frameworks",
554 | "@loader_path/Frameworks",
555 | );
556 | PRODUCT_BUNDLE_IDENTIFIER = shenzhiqiang.MultilevelMenuOCTests;
557 | PRODUCT_NAME = "$(TARGET_NAME)";
558 | TARGETED_DEVICE_FAMILY = "1,2";
559 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MultilevelMenuOC.app/MultilevelMenuOC";
560 | };
561 | name = Debug;
562 | };
563 | 4993E80822FD53BF001EEB63 /* Release */ = {
564 | isa = XCBuildConfiguration;
565 | buildSettings = {
566 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
567 | BUNDLE_LOADER = "$(TEST_HOST)";
568 | CODE_SIGN_STYLE = Automatic;
569 | DEVELOPMENT_TEAM = RJUJXP82S4;
570 | INFOPLIST_FILE = MultilevelMenuOCTests/Info.plist;
571 | LD_RUNPATH_SEARCH_PATHS = (
572 | "$(inherited)",
573 | "@executable_path/Frameworks",
574 | "@loader_path/Frameworks",
575 | );
576 | PRODUCT_BUNDLE_IDENTIFIER = shenzhiqiang.MultilevelMenuOCTests;
577 | PRODUCT_NAME = "$(TARGET_NAME)";
578 | TARGETED_DEVICE_FAMILY = "1,2";
579 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MultilevelMenuOC.app/MultilevelMenuOC";
580 | };
581 | name = Release;
582 | };
583 | 4993E80A22FD53BF001EEB63 /* Debug */ = {
584 | isa = XCBuildConfiguration;
585 | buildSettings = {
586 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
587 | CODE_SIGN_STYLE = Automatic;
588 | DEVELOPMENT_TEAM = RJUJXP82S4;
589 | INFOPLIST_FILE = MultilevelMenuOCUITests/Info.plist;
590 | LD_RUNPATH_SEARCH_PATHS = (
591 | "$(inherited)",
592 | "@executable_path/Frameworks",
593 | "@loader_path/Frameworks",
594 | );
595 | PRODUCT_BUNDLE_IDENTIFIER = shenzhiqiang.MultilevelMenuOCUITests;
596 | PRODUCT_NAME = "$(TARGET_NAME)";
597 | TARGETED_DEVICE_FAMILY = "1,2";
598 | TEST_TARGET_NAME = MultilevelMenuOC;
599 | };
600 | name = Debug;
601 | };
602 | 4993E80B22FD53BF001EEB63 /* Release */ = {
603 | isa = XCBuildConfiguration;
604 | buildSettings = {
605 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
606 | CODE_SIGN_STYLE = Automatic;
607 | DEVELOPMENT_TEAM = RJUJXP82S4;
608 | INFOPLIST_FILE = MultilevelMenuOCUITests/Info.plist;
609 | LD_RUNPATH_SEARCH_PATHS = (
610 | "$(inherited)",
611 | "@executable_path/Frameworks",
612 | "@loader_path/Frameworks",
613 | );
614 | PRODUCT_BUNDLE_IDENTIFIER = shenzhiqiang.MultilevelMenuOCUITests;
615 | PRODUCT_NAME = "$(TARGET_NAME)";
616 | TARGETED_DEVICE_FAMILY = "1,2";
617 | TEST_TARGET_NAME = MultilevelMenuOC;
618 | };
619 | name = Release;
620 | };
621 | /* End XCBuildConfiguration section */
622 |
623 | /* Begin XCConfigurationList section */
624 | 4993E7D222FD53BD001EEB63 /* Build configuration list for PBXProject "MultilevelMenuOC" */ = {
625 | isa = XCConfigurationList;
626 | buildConfigurations = (
627 | 4993E80122FD53BF001EEB63 /* Debug */,
628 | 4993E80222FD53BF001EEB63 /* Release */,
629 | );
630 | defaultConfigurationIsVisible = 0;
631 | defaultConfigurationName = Release;
632 | };
633 | 4993E80322FD53BF001EEB63 /* Build configuration list for PBXNativeTarget "MultilevelMenuOC" */ = {
634 | isa = XCConfigurationList;
635 | buildConfigurations = (
636 | 4993E80422FD53BF001EEB63 /* Debug */,
637 | 4993E80522FD53BF001EEB63 /* Release */,
638 | );
639 | defaultConfigurationIsVisible = 0;
640 | defaultConfigurationName = Release;
641 | };
642 | 4993E80622FD53BF001EEB63 /* Build configuration list for PBXNativeTarget "MultilevelMenuOCTests" */ = {
643 | isa = XCConfigurationList;
644 | buildConfigurations = (
645 | 4993E80722FD53BF001EEB63 /* Debug */,
646 | 4993E80822FD53BF001EEB63 /* Release */,
647 | );
648 | defaultConfigurationIsVisible = 0;
649 | defaultConfigurationName = Release;
650 | };
651 | 4993E80922FD53BF001EEB63 /* Build configuration list for PBXNativeTarget "MultilevelMenuOCUITests" */ = {
652 | isa = XCConfigurationList;
653 | buildConfigurations = (
654 | 4993E80A22FD53BF001EEB63 /* Debug */,
655 | 4993E80B22FD53BF001EEB63 /* Release */,
656 | );
657 | defaultConfigurationIsVisible = 0;
658 | defaultConfigurationName = Release;
659 | };
660 | /* End XCConfigurationList section */
661 | };
662 | rootObject = 4993E7CF22FD53BD001EEB63 /* Project object */;
663 | }
664 |
--------------------------------------------------------------------------------