├── .gitignore
├── LICENSE
├── ManageGroup
├── GitHub最新下载地址.txt
├── ManageGroup.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── ManageGroup.xcworkspace
│ └── contents.xcworkspacedata
├── ManageGroup
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Contacts
│ │ ├── Controller
│ │ │ ├── BRContactsViewController.h
│ │ │ ├── BRContactsViewController.m
│ │ │ ├── BRGroupViewController.h
│ │ │ └── BRGroupViewController.m
│ │ ├── Model
│ │ │ ├── BRContactsModel.h
│ │ │ ├── BRContactsModel.m
│ │ │ ├── BRGroupModel.h
│ │ │ └── BRGroupModel.m
│ │ └── View
│ │ │ ├── BRContactsCell.h
│ │ │ ├── BRContactsCell.m
│ │ │ ├── BRSearchBar.h
│ │ │ ├── BRSearchBar.m
│ │ │ ├── BRSearchBarView.h
│ │ │ └── BRSearchBarView.m
│ ├── Info.plist
│ ├── PrefixHeader.pch
│ ├── Resource
│ │ ├── add@2x.png
│ │ ├── add@3x.png
│ │ ├── contacts.json
│ │ ├── default.jpg
│ │ ├── group_manage@2x.png
│ │ ├── group_manage@3x.png
│ │ ├── pulldownList@2x.png
│ │ └── pulldownList@3x.png
│ ├── Vendor
│ │ └── YYFPSLabel
│ │ │ ├── YYFPSLabel.h
│ │ │ ├── YYFPSLabel.m
│ │ │ ├── YYWeakProxy.h
│ │ │ └── YYWeakProxy.m
│ └── main.m
├── Podfile
├── Podfile.lock
├── Pods
│ ├── Headers
│ │ ├── Private
│ │ │ └── MJExtension
│ │ │ │ ├── MJExtension.h
│ │ │ │ ├── MJExtensionConst.h
│ │ │ │ ├── MJFoundation.h
│ │ │ │ ├── MJProperty.h
│ │ │ │ ├── MJPropertyKey.h
│ │ │ │ ├── MJPropertyType.h
│ │ │ │ ├── NSObject+MJClass.h
│ │ │ │ ├── NSObject+MJCoding.h
│ │ │ │ ├── NSObject+MJKeyValue.h
│ │ │ │ ├── NSObject+MJProperty.h
│ │ │ │ └── NSString+MJExtension.h
│ │ └── Public
│ │ │ └── MJExtension
│ │ │ ├── MJExtension.h
│ │ │ ├── MJExtensionConst.h
│ │ │ ├── MJFoundation.h
│ │ │ ├── MJProperty.h
│ │ │ ├── MJPropertyKey.h
│ │ │ ├── MJPropertyType.h
│ │ │ ├── NSObject+MJClass.h
│ │ │ ├── NSObject+MJCoding.h
│ │ │ ├── NSObject+MJKeyValue.h
│ │ │ ├── NSObject+MJProperty.h
│ │ │ └── NSString+MJExtension.h
│ ├── MJExtension
│ │ ├── LICENSE
│ │ ├── MJExtension
│ │ │ ├── MJExtension.h
│ │ │ ├── MJExtensionConst.h
│ │ │ ├── MJExtensionConst.m
│ │ │ ├── MJFoundation.h
│ │ │ ├── MJFoundation.m
│ │ │ ├── MJProperty.h
│ │ │ ├── MJProperty.m
│ │ │ ├── MJPropertyKey.h
│ │ │ ├── MJPropertyKey.m
│ │ │ ├── MJPropertyType.h
│ │ │ ├── MJPropertyType.m
│ │ │ ├── NSObject+MJClass.h
│ │ │ ├── NSObject+MJClass.m
│ │ │ ├── NSObject+MJCoding.h
│ │ │ ├── NSObject+MJCoding.m
│ │ │ ├── NSObject+MJKeyValue.h
│ │ │ ├── NSObject+MJKeyValue.m
│ │ │ ├── NSObject+MJProperty.h
│ │ │ ├── NSObject+MJProperty.m
│ │ │ ├── NSString+MJExtension.h
│ │ │ └── NSString+MJExtension.m
│ │ └── README.md
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ │ └── project.pbxproj
│ └── Target Support Files
│ │ ├── MJExtension
│ │ ├── MJExtension-dummy.m
│ │ ├── MJExtension-prefix.pch
│ │ └── MJExtension.xcconfig
│ │ └── Pods-ManageGroup
│ │ ├── Pods-ManageGroup-acknowledgements.markdown
│ │ ├── Pods-ManageGroup-acknowledgements.plist
│ │ ├── Pods-ManageGroup-dummy.m
│ │ ├── Pods-ManageGroup-frameworks.sh
│ │ ├── Pods-ManageGroup-resources.sh
│ │ ├── Pods-ManageGroup.debug.xcconfig
│ │ └── Pods-ManageGroup.release.xcconfig
├── a.png
└── 效果图.gif
└── README.md
/.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 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | # CocoaPods
31 | #
32 | # We recommend against adding the Pods directory to your .gitignore. However
33 | # you should judge for yourself, the pros and cons are mentioned at:
34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
35 | #
36 | # Pods/
37 |
38 | # Carthage
39 | #
40 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
41 | # Carthage/Checkouts
42 |
43 | Carthage/Build
44 |
45 | # fastlane
46 | #
47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
48 | # screenshots whenever they are needed.
49 | # For more information about the recommended setup visit:
50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
51 |
52 | fastlane/report.xml
53 | fastlane/screenshots
54 |
55 | #Code Injection
56 | #
57 | # After new code Injection tools there's a generated folder /iOSInjectionProject
58 | # https://github.com/johnno1962/injectionforxcode
59 |
60 | iOSInjectionProject/
61 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/ManageGroup/GitHub最新下载地址.txt:
--------------------------------------------------------------------------------
1 | 喜欢的朋友😍star支持一下👍!
2 | GitHub最新下载地址:https://github.com/borenfocus/ManageGroup
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/22.
6 | // Copyright © 2017年 renbo. 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 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/22.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "BRContactsViewController.h"
11 | #import "YYFPSLabel.h"
12 |
13 | @interface AppDelegate ()
14 |
15 | @end
16 |
17 | @implementation AppDelegate
18 |
19 |
20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
21 | self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
22 | [self setupRootViewController];
23 | [self.window makeKeyAndVisible];
24 |
25 | // 添加 显示FPS(刷新帧率,画面每秒传输的帧数)
26 | [self showFPSLabel];
27 |
28 | return YES;
29 | }
30 |
31 | #pragma mark - 设置根视图控制器
32 | - (void)setupRootViewController {
33 | BRContactsViewController *contactsVC = [[BRContactsViewController alloc]init];
34 | UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:contactsVC];
35 | // 设置状态栏前景色为白色
36 | nav.navigationBar.barStyle = UIBarStyleBlack;
37 | // 设置navigationBar背景颜色
38 | nav.navigationBar.barTintColor = RGB_HEX(0x349DDA);
39 | // 设置navigationBar所有子控件的颜色
40 | nav.navigationBar.tintColor = [UIColor whiteColor];
41 | // 设置 title 颜色
42 | [nav.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
43 | self.window.rootViewController = nav;
44 | }
45 |
46 | #pragma mark - 添加 YYFPSLabel
47 | - (void)showFPSLabel {
48 | YYFPSLabel *fpsLabel = [[YYFPSLabel alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 50) / 2, 100, 50, 20)];
49 | [[UIApplication sharedApplication].keyWindow addSubview:fpsLabel];
50 | }
51 |
52 | - (void)applicationWillResignActive:(UIApplication *)application {
53 | // 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.
54 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
55 | }
56 |
57 |
58 | - (void)applicationDidEnterBackground:(UIApplication *)application {
59 | // 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.
60 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
61 | }
62 |
63 |
64 | - (void)applicationWillEnterForeground:(UIApplication *)application {
65 | // 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.
66 | }
67 |
68 |
69 | - (void)applicationDidBecomeActive:(UIApplication *)application {
70 | // 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.
71 | }
72 |
73 |
74 | - (void)applicationWillTerminate:(UIApplication *)application {
75 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
76 | }
77 |
78 |
79 | @end
80 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/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 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/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 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/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 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Controller/BRContactsViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // BRContactsViewController.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface BRContactsViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Controller/BRContactsViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // BRContactsViewController.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 | // 最新代码下载地址:https://github.com/borenfocus/ManageGroup
9 |
10 | #import "BRContactsViewController.h"
11 | #import "BRContactsCell.h"
12 | #import "BRContactsModel.h"
13 | #import "BRGroupModel.h"
14 | #import "BRGroupViewController.h"
15 | #import "BRSearchBarView.h"
16 | #import
17 |
18 | @interface BRContactsViewController ()
19 | {
20 | NSIndexPath *_indexPath; // 保存当前选中的单元格
21 | }
22 | /** 搜索框视图 */
23 | @property (nonatomic,strong) BRSearchBarView *searchBarView;
24 | @property (nonatomic, strong) UITableView *tableView;
25 | /** 保存分组数据模型 */
26 | @property (nonatomic, strong) NSMutableArray *groupModelArr;
27 | /** 保存旋转状态(展开/折叠) */
28 | @property (nonatomic, strong) NSMutableArray *switchArr;
29 |
30 | @end
31 |
32 | @implementation BRContactsViewController
33 |
34 | - (void)viewDidLoad {
35 | [super viewDidLoad];
36 | self.navigationItem.title = @"联系人";
37 | self.automaticallyAdjustsScrollViewInsets = NO;
38 | self.view.backgroundColor = [UIColor redColor];
39 | [self initUI];
40 | [self loadData];
41 | }
42 |
43 | - (void)initUI {
44 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:[self getGroupManageButton]];
45 | self.tableView.hidden = NO;
46 | }
47 |
48 | - (void)loadData {
49 | self.groupModelArr = nil;
50 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
51 | // 加载本地数据(实际开发中这里写网络请求,从服务端请求数据...)
52 | NSString *filePath = [[NSBundle mainBundle]pathForResource:@"contacts" ofType:@"json"];
53 | NSData *data = [NSData dataWithContentsOfFile:filePath];
54 | NSDictionary *jsonObj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
55 | NSLog(@"数据内容:%@", jsonObj);
56 | NSString *retCode = jsonObj[@"ret_code"];
57 | if ([retCode isEqualToString:successFlag]) {
58 | // 解析返回的结果:JSON转数据模型
59 | NSMutableArray *groupModelArr = [BRGroupModel mj_objectArrayWithKeyValuesArray:jsonObj[@"groups"]];
60 | self.groupModelArr = groupModelArr;
61 |
62 | for (NSInteger i = 0; i < self.groupModelArr.count; i++) {
63 | // 加个判断,防止多次重复调用这个方法时,造成数据累加无限添加
64 | if (self.switchArr.count < self.groupModelArr.count) {
65 | [self.switchArr addObject:@NO];
66 | }
67 | }
68 | // 回到主线程刷新表格
69 | dispatch_async(dispatch_get_main_queue(), ^{
70 | [self.tableView reloadData];
71 | });
72 | }
73 | });
74 | }
75 |
76 | - (UIButton *)getGroupManageButton {
77 | // 设置左上角的返回按钮 (非根控制器才需要设置返回按钮)
78 | UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 31, 22, 22)];
79 | [btn setImage:[UIImage imageNamed:@"group_manage"] forState:UIControlStateNormal];
80 | [btn addTarget:self action:@selector(clickToGroupManagement) forControlEvents:UIControlEventTouchUpInside];
81 | return btn;
82 | }
83 |
84 | - (void)clickToGroupManagement {
85 | BRGroupViewController *groupVC = [[BRGroupViewController alloc]init];
86 | groupVC.groupModelArr = self.groupModelArr; //传值
87 | [self.navigationController pushViewController:groupVC animated:YES];
88 | }
89 |
90 | - (BRSearchBarView *)searchBarView {
91 | if(_searchBarView == nil) {
92 | _searchBarView = [[BRSearchBarView alloc]initWithFrame:CGRectMake(0, kStatusBarAndNaviBarH, self.view.frame.size.width, 50)];
93 | }
94 | return _searchBarView;
95 | }
96 |
97 | #pragma mark- 懒加载视图
98 | - (UITableView *)tableView {
99 | if(_tableView == nil) {
100 | // 原点位置是(0,0)
101 | _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, kStatusBarAndNaviBarH, SCREEN_WIDTH, SCREEN_HEIGHT - 64)];
102 | _tableView.backgroundColor = [UIColor groupTableViewBackgroundColor];
103 | _tableView.delegate = self;
104 | _tableView.dataSource = self;
105 | // 设置表格头视图
106 | _tableView.tableHeaderView = self.searchBarView;
107 | [self.view addSubview:_tableView];
108 |
109 | }
110 | return _tableView;
111 | }
112 |
113 | #pragma mark- UITableViewDataSource, UITableViewDelegate
114 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
115 | return self.groupModelArr.count;
116 | }
117 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
118 | BRGroupModel *model = self.groupModelArr[section];
119 | if ([self.switchArr[section] boolValue] == YES) {
120 | return model.contacts.count;
121 | } else {
122 | return 0;
123 | }
124 | }
125 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
126 | BRContactsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
127 | if (!cell) {
128 | cell = [[BRContactsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
129 | }
130 | BRGroupModel *gModel = self.groupModelArr[indexPath.section];
131 | cell.model = gModel.contacts[indexPath.row];
132 | // 添加单元格的长按手势
133 | UILongPressGestureRecognizer *longPressed = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressToDo:)];
134 | longPressed.minimumPressDuration = 1;
135 | [cell.contentView addGestureRecognizer:longPressed];
136 | return cell;
137 | }
138 |
139 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
140 | [self.view endEditing:YES];
141 | // 取消选中后的高亮状态(默认是:选中单元格后一直处于高亮状态,直到下次重新选择)
142 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
143 | _indexPath = indexPath;
144 | // 获取当前患者对象,并传给详情页面
145 | BRGroupModel *gModel = self.groupModelArr[indexPath.section];
146 | BRContactsModel *model = gModel.contacts[indexPath.row];
147 | NSLog(@"点击了:%@", model.name);
148 | }
149 | /** 长按手势的执行方法 */
150 | - (void)longPressToDo:(UILongPressGestureRecognizer *)gesture {
151 | if(gesture.state == UIGestureRecognizerStateBegan) {
152 | CGPoint point = [gesture locationInView:self.tableView];
153 | _indexPath = [self.tableView indexPathForRowAtPoint:point];
154 | // 弹出框
155 | [self gestureAlert];
156 | if(_indexPath == nil) return ;
157 | }
158 | }
159 | /** 弹出框方法 */
160 | - (void)gestureAlert {
161 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
162 | [alert addAction:[UIAlertAction actionWithTitle:@"删除" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
163 | NSLog(@"点击了删除");
164 | }]];
165 | [alert addAction:[UIAlertAction actionWithTitle:@"移至分组" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
166 | NSLog(@"点击了移至分组");
167 | }]];
168 | [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
169 | [self presentViewController:alert animated:YES completion:nil];
170 | }
171 |
172 | // 行高
173 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
174 | return 60 / 375.0 * SCREEN_WIDTH;
175 | }
176 | // 分区头的高度
177 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
178 | return 50 / 375.0 * SCREEN_WIDTH;
179 | }
180 | // 分区尾的高度
181 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
182 | if (section == 0) {
183 | return 10.0f;
184 | } else {
185 | return 1.0f;
186 | }
187 | }
188 |
189 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
190 | UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320 / 375.0 * SCREEN_WIDTH, 50 / 375.0 * SCREEN_WIDTH)];
191 | view.backgroundColor = [UIColor whiteColor];
192 | // 边界线
193 | UIView *borderView = [[UIView alloc]initWithFrame:CGRectMake(0, 50 / 375.0 * SCREEN_WIDTH, SCREEN_WIDTH, 0.5)];
194 | borderView.backgroundColor = RGB_HEX(0xC8C7CC);
195 | [view addSubview:borderView];
196 | // 展开箭头
197 | UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(15 / 375.0 * SCREEN_WIDTH, 19 / 375.0 * SCREEN_WIDTH, 14 / 375.0 * SCREEN_WIDTH, 12 / 375.0 * SCREEN_WIDTH)];
198 | imageView.image = [UIImage imageNamed:@"pulldownList.png"];
199 | [view addSubview:imageView];
200 | // 分组名Label
201 | UILabel *groupLable = [[UILabel alloc]initWithFrame:CGRectMake(45 / 375.0 * SCREEN_WIDTH, 0, SCREEN_WIDTH, 50 / 375.0 * SCREEN_WIDTH)];
202 | BRGroupModel *model = _groupModelArr[section];
203 | groupLable.text = [NSString stringWithFormat:@"%@ [ %ld ]", model.groupName, (long)model.memberNum];
204 | groupLable.textColor = [UIColor colorWithRed:0.21 green:0.21 blue:0.21 alpha:1.0];
205 | groupLable.font = [UIFont systemFontOfSize:16];
206 | [view addSubview:groupLable];
207 |
208 | view.userInteractionEnabled = YES;
209 | // 初始化一个手势
210 | UITapGestureRecognizer *myTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(openClick:)];
211 | // 给view添加手势
212 | [view addGestureRecognizer:myTap];
213 | view.tag = 1000 + section;
214 |
215 | CGFloat rota;
216 | if ([self.switchArr[section] boolValue] == NO) {
217 | rota = 0;
218 | } else {
219 | rota = M_PI_2; //π/2
220 | }
221 | imageView.transform = CGAffineTransformMakeRotation(rota);//箭头偏移π/2
222 | return view;
223 | }
224 |
225 | - (void)openClick:(UITapGestureRecognizer *)sender {
226 | [self.view endEditing:YES];
227 | NSInteger section = sender.view.tag - 1000;
228 | if ([self.switchArr[section] boolValue] == NO) {
229 | [self.switchArr replaceObjectAtIndex:section withObject:@YES];
230 | } else {
231 | [self.switchArr replaceObjectAtIndex:section withObject:@NO];
232 | }
233 | if (section >= 0) {
234 | // 刷新分区
235 | [_tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationAutomatic];
236 | }
237 | }
238 |
239 | - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
240 | UIView *clearView = [[UIView alloc]init];
241 | clearView.backgroundColor = [UIColor clearColor];
242 | return clearView;
243 | }
244 |
245 | - (NSMutableArray *)groupModelArr {
246 | if (!_groupModelArr) {
247 | _groupModelArr = [[NSMutableArray alloc] init];
248 | }
249 | return _groupModelArr;
250 | }
251 |
252 | - (NSMutableArray *)switchArr {
253 | if (!_switchArr) {
254 | _switchArr = [[NSMutableArray alloc]init];
255 | }
256 | return _switchArr;
257 | }
258 |
259 | @end
260 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Controller/BRGroupViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // BRGroupViewController.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface BRGroupViewController : UIViewController
12 | /** 接收传过来的 分组模型对象 数组 */
13 | @property (nonatomic, strong) NSMutableArray *groupModelArr;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Controller/BRGroupViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // BRGroupViewController.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 | // 最新代码下载地址:https://github.com/borenfocus/ManageGroup
9 |
10 | #import "BRGroupViewController.h"
11 | #import "BRGroupModel.h"
12 |
13 | @interface BRGroupViewController ()
14 | {
15 | NSIndexPath *_indexPath; // 保存当前选中的单元格
16 | }
17 | @property (nonatomic, strong) UITableView *tableView;
18 | @property (nonatomic, strong) UIView *addHeadView;
19 | @end
20 |
21 | @implementation BRGroupViewController
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | self.navigationItem.title = @"分组管理";
26 | [self initUI];
27 | }
28 |
29 | - (void)initUI {
30 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"编辑" style:UIBarButtonItemStyleDone target:self action:@selector(clickEditBtn:)];
31 | self.tableView.hidden = NO;
32 | }
33 |
34 | - (void)clickEditBtn:(UIBarButtonItem *)sender {
35 | NSLog(@"点击了编辑按钮");
36 | //设置tableView的编辑状态
37 | _tableView.editing = !_tableView.editing;
38 | if (_tableView.isEditing == YES) {
39 | sender.title = @"完成";
40 | } else {
41 | sender.title = @"编辑";
42 | }
43 | }
44 |
45 | #pragma mark- 懒加载视图
46 | - (UITableView *)tableView {
47 | if(_tableView == nil) {
48 | _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
49 | _tableView.backgroundColor = [UIColor groupTableViewBackgroundColor];
50 | _tableView.delegate = self;
51 | _tableView.dataSource = self;
52 | _tableView.tableHeaderView = self.addHeadView;
53 | _tableView.tableFooterView = [[UIView alloc]init];
54 | _tableView.tableFooterView.backgroundColor = [UIColor groupTableViewBackgroundColor];
55 | [self.view addSubview:_tableView];
56 | }
57 | return _tableView;
58 | }
59 | - (UIView *)addHeadView {
60 | if(_addHeadView == nil) {
61 | _addHeadView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 60)];
62 | _addHeadView.backgroundColor = [UIColor whiteColor];
63 | UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 14, 32, 32)];
64 | imageView.image = [UIImage imageNamed:@"add.png"];
65 | [_addHeadView addSubview:imageView];
66 | UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(52, 0, 100, 60)];
67 | label.font = [UIFont boldSystemFontOfSize:16];
68 | label.text = @"添加分组";
69 | [_addHeadView addSubview:label];
70 | UIView *view1 = [[UIView alloc]initWithFrame:CGRectMake(0, 60 - 0.5, SCREEN_WIDTH, 0.5)];
71 | view1.backgroundColor = RGB_HEX(0xC8C7CC);
72 | [_addHeadView addSubview:view1];
73 | UIButton *addBtn = [UIButton buttonWithType:UIButtonTypeSystem];
74 | addBtn.frame = CGRectMake(0, 0, SCREEN_WIDTH, 60);
75 | [addBtn addTarget:self action:@selector(addGroupAlert) forControlEvents:UIControlEventTouchUpInside];
76 | [_addHeadView addSubview:addBtn];
77 | [_tableView.tableHeaderView addSubview:_addHeadView];
78 | }
79 | return _addHeadView;
80 | }
81 |
82 | /** 弹出框 */
83 | - (void)addGroupAlert {
84 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"添加分组" message:@"请输入新的分组名称" preferredStyle:UIAlertControllerStyleAlert];
85 | //添加有文本输入框
86 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
87 | textField.placeholder = @"请输入分组名";
88 | //设置文本清空按钮
89 | textField.clearButtonMode = UITextFieldViewModeAlways;
90 | }];
91 | [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
92 | // 读取文本框的值显示出来
93 | UITextField *addGroupTF = alert.textFields.firstObject;
94 | NSLog(@"新添加的分组名:%@", addGroupTF.text);
95 | // 发送添加请求...
96 | }]];
97 | [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
98 | [self presentViewController:alert animated:YES completion:nil];
99 | }
100 |
101 | #pragma mark- UITableViewDataSource, UITableViewDelegate
102 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
103 | return 1;
104 | }
105 |
106 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
107 | return _groupModelArr.count;
108 | }
109 |
110 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
111 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
112 | if (!cell) {
113 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
114 | }
115 | if (indexPath.row != 0) {
116 | cell.textLabel.textColor = RGB_HEX(0x363636);
117 | cell.textLabel.font = [UIFont systemFontOfSize:16];
118 | BRGroupModel *model = _groupModelArr[indexPath.row];
119 | cell.textLabel.text = model.groupName;
120 | }
121 | return cell;
122 | }
123 |
124 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
125 | //取消选中后的高亮状态(默认是:选中单元格后一直处于高亮状态,直到下次重新选择)
126 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
127 | _indexPath = indexPath;
128 | if (indexPath.row != 0) {
129 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"修改分组名" message:@"请输入新的分组名称" preferredStyle:UIAlertControllerStyleAlert];
130 | //添加有文本输入框
131 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
132 | textField.placeholder = @"请输入分组名";
133 | //设置文本清空按钮
134 | textField.clearButtonMode = UITextFieldViewModeAlways;
135 | }];
136 | [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
137 | // 读取文本框的值显示出来
138 | UITextField *alterGroupTF = alert.textFields.firstObject;
139 | NSLog(@"新修改的分组名:%@", alterGroupTF.text);
140 | // 发送修改请求...
141 | }]];
142 | [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
143 | [self presentViewController:alert animated:YES completion:nil];
144 | }
145 | }
146 |
147 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
148 | if (indexPath.row == 0) {
149 | return 0;
150 | } else {
151 | return 50 / 375.0 * SCREEN_WIDTH;
152 | }
153 | }
154 |
155 | /** 指定哪些行的 cell 可以进行编辑 (UITableViewDataSource 协议方法) */
156 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
157 | if (indexPath.row == 0) {
158 | return NO; // 第一行不能编辑
159 | } else {
160 | return YES;
161 | }
162 | }
163 |
164 | #pragma mark --删除cell
165 | /** 1.单元格返回的编辑风格(添加/删除/不可编辑,三种风格)(UITableViewDelegate协议中方法) */
166 | - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
167 | return UITableViewCellEditingStyleDelete;
168 | }
169 |
170 | /** 2.提交编辑状态/效果 (UITableViewDataSource协议中方法) */
171 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
172 | #pragma mark- 点击 删除 按钮的操作
173 | //判断编辑状态是删除时
174 | if (editingStyle == UITableViewCellEditingStyleDelete) {
175 | BRGroupModel *dModel = _groupModelArr[indexPath.row];
176 | if (dModel.memberNum == 0) {
177 | NSLog(@"删除分组!");
178 | //1. 更新数据源(数组): 根据indexPaht.row作为数组下标, 从数组中删除数据
179 | //[self.groupModelArr removeObjectAtIndex:indexPath.row];
180 | //2. TableView中 删除一个cell (以动画的形式删除指定的cell)
181 | //[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
182 | // 发送删除请求...
183 | } else {
184 | NSLog(@"组内有成员,不能删除!");
185 | }
186 | }
187 | }
188 |
189 | #pragma mark- 移动
190 | /** 1.指定tableView那些行(cell)可以移动 */
191 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
192 | if (indexPath.row == 0) {
193 | return NO; //cell不能移动
194 | } else {
195 | return YES; //cell可以移动
196 | }
197 | }
198 | /** 2.移动cell后的操作:数据源进行更新 */
199 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
200 | //1. 存储将要被移动的位置的对象
201 | NSString *str = [_groupModelArr objectAtIndex:sourceIndexPath.row];
202 | //2. 将对象从原位置移除
203 | [self.groupModelArr removeObjectAtIndex:sourceIndexPath.row];
204 | //3. 将对象插入到新位置
205 | [self.groupModelArr insertObject:str atIndex:destinationIndexPath.row];
206 | //刷新表格
207 | [self.tableView reloadData];
208 | }
209 |
210 | //点击左边删除按钮时,显示的右边删除button的title
211 | - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
212 | return @"删除分组";
213 | }
214 |
215 | - (NSMutableArray *)groupModelArr {
216 | if(_groupModelArr == nil) {
217 | _groupModelArr = [[NSMutableArray alloc] init];
218 | }
219 | return _groupModelArr;
220 | }
221 |
222 | #pragma mark- cell分割线左对齐(两个方法)
223 | - (void)viewDidLayoutSubviews {
224 | if ([_tableView respondsToSelector:@selector(setSeparatorInset:)]) {
225 | [_tableView setSeparatorInset:UIEdgeInsetsZero];
226 | }
227 | if ([_tableView respondsToSelector:@selector(setLayoutMargins:)]) {
228 | [_tableView setLayoutMargins:UIEdgeInsetsZero];
229 | }
230 | }
231 | - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPat{
232 | if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
233 | [cell setLayoutMargins:UIEdgeInsetsZero];
234 | }
235 | if ([cell respondsToSelector:@selector(setSeparatorInset:)]){
236 | [cell setSeparatorInset:UIEdgeInsetsZero];
237 | }
238 | }
239 |
240 |
241 | @end
242 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Model/BRContactsModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // BRContactsModel.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface BRContactsModel : NSObject
12 | /** 用户ID */
13 | @property (nonatomic, copy) NSString *ID;
14 | /** 头像 */
15 | @property (nonatomic, copy) NSString *headImg;
16 | /** 姓名 */
17 | @property (nonatomic, copy) NSString *name;
18 | /** 描述 */
19 | @property (nonatomic, copy) NSString *desc;
20 | /** 活动时间(表示与该联系人的最后交流时间) */
21 | @property (nonatomic, copy) NSString *activeTime;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Model/BRContactsModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // BRContactsModel.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import "BRContactsModel.h"
10 | #import
11 |
12 | @implementation BRContactsModel
13 |
14 | #pragma mark - 将属性名换为其他key去字典中取值(避免属性名为系统关键字)
15 | + (NSDictionary *)mj_replacedKeyFromPropertyName {
16 | return @{
17 | @"ID" : @"id",
18 | @"desc" : @"description"
19 | };
20 | }
21 |
22 | #pragma mark - 驼峰属性转成下划线key去字典中取值
23 | + (id)mj_replacedKeyFromPropertyName121:(NSString *)propertyName {
24 | return [propertyName mj_underlineFromCamel];
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Model/BRGroupModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // BRGroupModel.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface BRGroupModel : NSObject
12 | /** 分组ID */
13 | @property (nonatomic, copy) NSString *groupId;
14 | /** 分组名称 */
15 | @property (nonatomic, copy) NSString *groupName;
16 | /** 分组类型(1表示未分组, 2表示自定义分组) */
17 | @property (nonatomic, assign) NSInteger groupType;
18 | /** 成员个数(患者个数) */
19 | @property (nonatomic, assign) NSInteger memberNum;
20 | /** 分组下的好友列表 */
21 | @property (nonatomic, strong) NSArray *contacts;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/Model/BRGroupModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // BRGroupModel.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import "BRGroupModel.h"
10 | #import
11 | #import "BRContactsModel.h"
12 |
13 | @implementation BRGroupModel
14 |
15 | #pragma mark - 驼峰属性转成下划线key去字典中取值
16 | + (id)mj_replacedKeyFromPropertyName121:(NSString *)propertyName {
17 | return [propertyName mj_underlineFromCamel];
18 | }
19 |
20 | #pragma mark - 属性为数组类型时,要指定数组元素对应的模型类(解析类)
21 | + (NSDictionary *)mj_objectClassInArray {
22 | return @{@"contacts": [BRContactsModel class]};
23 | }
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/View/BRContactsCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // BRContactsCell.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class BRContactsModel;
12 | @interface BRContactsCell : UITableViewCell
13 | /** 组员模型对象 */
14 | @property (nonatomic, strong) BRContactsModel *model;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/View/BRContactsCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // BRContactsCell.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import "BRContactsCell.h"
10 | #import "BRContactsModel.h"
11 |
12 | // 等比例适配系数
13 | #define kScaleFit (SCREEN_WIDTH / 375.0f)
14 |
15 | @interface BRContactsCell ()
16 | @property (nonatomic, strong) UIImageView *iconImageView;
17 | @property (nonatomic, strong) UILabel *nameLabel;
18 | @property (nonatomic, strong) UILabel *describeLabel;
19 | @property (nonatomic, strong) UILabel *activeTimeLabel;
20 |
21 | @end
22 |
23 | @implementation BRContactsCell
24 | #pragma mark - 初始化
25 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
26 | if ([super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
27 | [self.contentView addSubview:self.iconImageView];
28 | [self.contentView addSubview:self.nameLabel];
29 | [self.contentView addSubview:self.describeLabel];
30 | [self.contentView addSubview:self.activeTimeLabel];
31 | }
32 | return self;
33 | }
34 |
35 | #pragma mark - setter
36 | - (void)setModel:(BRContactsModel *)model {
37 | _model = model;
38 | _iconImageView.image = [UIImage imageNamed:@"default.jpg"];
39 | _nameLabel.text = model.name;
40 | _describeLabel.text = model.desc;
41 | _activeTimeLabel.text = model.activeTime;
42 | }
43 |
44 | #pragma mark - 设置子视图的frame
45 | - (void)layoutSubviews {
46 | [super layoutSubviews];
47 | self.iconImageView.frame = CGRectMake(10, 6 * kScaleFit, 48 * kScaleFit, 48 * kScaleFit);
48 | self.nameLabel.frame = CGRectMake(10 + 56 * kScaleFit, 10 * kScaleFit, 150 * kScaleFit, 20 * kScaleFit);
49 | self.describeLabel.frame = CGRectMake(10 + 56 * kScaleFit, 35 * kScaleFit, 210 * kScaleFit, 15 * kScaleFit);
50 | self.activeTimeLabel.frame = CGRectMake(SCREEN_WIDTH - 100 * kScaleFit - 10, 10 * kScaleFit, 100 * kScaleFit, 20 * kScaleFit);
51 | }
52 |
53 | #pragma mark - 懒加载
54 | - (UIImageView *)iconImageView {
55 | if(_iconImageView == nil) {
56 | _iconImageView = [[UIImageView alloc] init];
57 | _iconImageView.layer.cornerRadius = 24 / 375.0 * SCREEN_WIDTH;
58 | _iconImageView.layer.masksToBounds = YES;
59 | }
60 | return _iconImageView;
61 | }
62 |
63 | - (UILabel *)nameLabel {
64 | if(_nameLabel == nil) {
65 | _nameLabel = [[UILabel alloc] init];
66 | _nameLabel.textColor = [UIColor colorWithRed:0.21 green:0.21 blue:0.21 alpha:1.0];
67 | _nameLabel.font = [UIFont systemFontOfSize:16];
68 | }
69 | return _nameLabel;
70 | }
71 |
72 | - (UILabel *)describeLabel {
73 | if(_describeLabel == nil) {
74 | _describeLabel = [[UILabel alloc] init];
75 | _describeLabel.textColor = [UIColor colorWithRed:0.45 green:0.45 blue:0.45 alpha:1.0];
76 | _describeLabel.font = [UIFont systemFontOfSize:12];
77 | }
78 | return _describeLabel;
79 | }
80 |
81 | - (UILabel *)activeTimeLabel {
82 | if(_activeTimeLabel == nil) {
83 | _activeTimeLabel = [[UILabel alloc] init];
84 | _activeTimeLabel.textColor = [UIColor colorWithRed:0.45 green:0.45 blue:0.45 alpha:1.0];
85 | _activeTimeLabel.textAlignment = NSTextAlignmentRight;
86 | _activeTimeLabel.font = [UIFont systemFontOfSize:12];
87 | }
88 | return _activeTimeLabel;
89 | }
90 |
91 |
92 | @end
93 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/View/BRSearchBar.h:
--------------------------------------------------------------------------------
1 | //
2 | // BRSearchBar.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface BRSearchBar : UISearchBar
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/View/BRSearchBar.m:
--------------------------------------------------------------------------------
1 | //
2 | // BRSearchBar.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import "BRSearchBar.h"
10 |
11 | @implementation BRSearchBar
12 | - (instancetype)initWithFrame:(CGRect)frame {
13 | self = [super initWithFrame:frame];
14 | if (!self) {
15 | return self;
16 | }
17 | return self;
18 | }
19 |
20 | -(void)layoutSubviews {
21 | [super layoutSubviews];
22 | UITextField *searchField;
23 | NSArray *subviewArr = self.subviews;
24 | for(int i = 0; i < subviewArr.count ; i++) {
25 | UIView *viewSub = [subviewArr objectAtIndex:i];
26 | NSArray *arrSub = viewSub.subviews;
27 | for (int j = 0; j < arrSub.count ; j++) {
28 | id tempId = [arrSub objectAtIndex:j];
29 | if([tempId isKindOfClass:[UITextField class]]) {
30 | searchField = (UITextField *)tempId;
31 | }
32 | }
33 | }
34 | //自定义UISearchBar
35 | if(searchField) {
36 | searchField.placeholder = @"搜索";
37 | searchField.borderStyle = UITextBorderStyleRoundedRect;
38 | searchField.backgroundColor = [UIColor whiteColor];
39 | searchField.textColor = [UIColor blackColor];
40 | SEL centerSelector = NSSelectorFromString([NSString stringWithFormat:@"%@ %@", @"setCenter", @"Placeholder:"]);
41 | if ([self respondsToSelector:centerSelector]) {
42 | NSMethodSignature *signature = [[UISearchBar class] instanceMethodSignatureForSelector:centerSelector];
43 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
44 | invocation.target = self;
45 | invocation.selector = centerSelector;
46 | [invocation invoke];
47 | }
48 | }
49 |
50 | //外部背景
51 | UIView *outView = [[UIView alloc] initWithFrame:self.bounds];
52 | [outView setBackgroundColor:[UIColor whiteColor]];
53 | [self insertSubview:outView atIndex:1];
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/View/BRSearchBarView.h:
--------------------------------------------------------------------------------
1 | //
2 | // BRSearchBarView.h
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface BRSearchBarView : UIView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Contacts/View/BRSearchBarView.m:
--------------------------------------------------------------------------------
1 | //
2 | // BRSearchBarView.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #import "BRSearchBarView.h"
10 | #import "BRSearchBar.h"
11 |
12 | @interface BRSearchBarView ()
13 | /** 搜索框 */
14 | @property (nonatomic,strong) BRSearchBar *searchBar;
15 |
16 | @end
17 | @implementation BRSearchBarView
18 | - (instancetype)initWithFrame:(CGRect)frame {
19 | if (self = [super initWithFrame:frame]) {
20 | [self addSubview:self.searchBar];
21 | }
22 | return self;
23 | }
24 |
25 | - (BRSearchBar *)searchBar {
26 | if (!_searchBar) {
27 | _searchBar = [[BRSearchBar alloc]initWithFrame:CGRectZero];
28 | _searchBar.layer.cornerRadius = 15;
29 | _searchBar.layer.masksToBounds = YES;
30 | _searchBar.layer.borderWidth = 0.5;
31 | _searchBar.layer.borderColor = [UIColor grayColor].CGColor;
32 | _searchBar.delegate = self;
33 | _searchBar.frame = CGRectMake(20, 10, SCREEN_WIDTH - 40, 30);
34 | }
35 | return _searchBar;
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
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 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/PrefixHeader.pch:
--------------------------------------------------------------------------------
1 | //
2 | // PrefixHeader.pch
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/23.
6 | // Copyright © 2017年 renbo. All rights reserved.
7 | //
8 |
9 | #ifndef PrefixHeader_pch
10 | #define PrefixHeader_pch
11 |
12 | #define kStatusBarAndNaviBarH 64
13 |
14 | //屏幕大小
15 | #define SCREEN_BOUNDS [[UIScreen mainScreen]bounds]
16 | #define SCREEN_WIDTH [[UIScreen mainScreen]bounds].size.width
17 | #define SCREEN_HEIGHT [[UIScreen mainScreen]bounds].size.height
18 |
19 | //返回数据成功
20 | #define successFlag @"0"
21 |
22 | // RGB颜色(10进制)
23 | #define RGB(r, g, b, a) [UIColor colorWithRed:(r) / 255.0 green:(g) / 255.0 blue:(b) / 255.0 alpha:(a)]
24 |
25 | // RGB颜色(16进制)
26 | #define RGB_HEX(rgbValue) \
27 | [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255.0 \
28 | green:((CGFloat)((rgbValue & 0xFF00) >> 8)) / 255.0 \
29 | blue:((CGFloat)(rgbValue & 0xFF)) / 255.0 alpha:1.0]
30 |
31 | #endif /* PrefixHeader_pch */
32 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/add@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/ManageGroup/Resource/add@2x.png
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/add@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/ManageGroup/Resource/add@3x.png
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/contacts.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": "1000",
3 | "ret_code": "0",
4 | "ret_msg": "操作成功",
5 | "groups": [
6 | {
7 | "group_id": "35ea5621962baa0e2b3dca2d4",
8 | "group_name": "未分组",
9 | "group_type": "1",
10 | "member_num": "3",
11 | "contacts": [
12 | {
13 | "id": "5848ead4d9e8d7b31172a285",
14 | "head_img": "default.png",
15 | "name": "张三",
16 | "description": "[WIFI在线] 欢迎给我留言",
17 | "active_time": "12:50"
18 | },
19 | {
20 | "id": "a243e23848ea43fddfs347b1",
21 | "head_img": "default.png",
22 | "name": "李四",
23 | "description": "[手机在线] 更新了日志",
24 | "active_time": "08:20"
25 | },
26 | {
27 | "id": "fsdfre522a43fddfs337b1",
28 | "head_img": "default.png",
29 | "name": "王五",
30 | "description": "[4G在线] 更新了说说",
31 | "active_time": "星期三"
32 | }
33 | ]
34 | },
35 | {
36 | "group_id": "80adasdas092dee232b74ca232",
37 | "group_name": "高中同学",
38 | "group_type": "2",
39 | "member_num": "2",
40 | "contacts": [
41 | {
42 | "id": "e323e65842ea43fd3sde367e4",
43 | "head_img": "default.png",
44 | "name": "小明",
45 | "description": "[电脑在线] 好好学习,天天向上",
46 | "active_time": "昨天"
47 | },
48 | {
49 | "id": "dwedwe3242cdw43fd3s3227e4",
50 | "head_img": "default.png",
51 | "name": "张小龙",
52 | "description": "[离线请留言] 哥是最牛逼的产品经理",
53 | "active_time": "2017/2/22"
54 | }
55 | ]
56 | },
57 | {
58 | "group_id": "dwe2357ec923e0e2b23a47",
59 | "group_name": "大学同学",
60 | "group_type": "2",
61 | "member_num": "1",
62 | "contacts": [
63 | {
64 | "id": "2dd4ddf65842dsd323d44fscsa21",
65 | "head_img": "default.png",
66 | "name": "乔布斯",
67 | "description": "[离线] 把产品做到极致",
68 | "active_time": "2017/2/22"
69 | }
70 | ]
71 | },
72 | {
73 | "group_id": "58ae5800963bee0e2b74ca48",
74 | "group_name": "同事",
75 | "group_type": "2",
76 | "member_num": "0"
77 | },
78 | {
79 | "group_id": "fdsds3233463bee0e2eeweffw",
80 | "group_name": "黑名单",
81 | "group_type": "2",
82 | "member_num": "0"
83 | }
84 | ]
85 | }
86 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/ManageGroup/Resource/default.jpg
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/group_manage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/ManageGroup/Resource/group_manage@2x.png
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/group_manage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/ManageGroup/Resource/group_manage@3x.png
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/pulldownList@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/ManageGroup/Resource/pulldownList@2x.png
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Resource/pulldownList@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/ManageGroup/Resource/pulldownList@3x.png
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Vendor/YYFPSLabel/YYFPSLabel.h:
--------------------------------------------------------------------------------
1 | //
2 | // YYFPSLabel.h
3 | // YYKitExample
4 | //
5 | // Created by ibireme on 15/9/3.
6 | // Copyright (c) 2015 ibireme. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | Show Screen FPS...
13 |
14 | The maximum fps in OSX/iOS Simulator is 60.00.
15 | The maximum fps on iPhone is 59.97.
16 | The maxmium fps on iPad is 60.0.
17 | */
18 | @interface YYFPSLabel : UILabel
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Vendor/YYFPSLabel/YYFPSLabel.m:
--------------------------------------------------------------------------------
1 | //
2 | // YYFPSLabel.m
3 | // YYKitExample
4 | //
5 | // Created by ibireme on 15/9/3.
6 | // Copyright (c) 2015 ibireme. All rights reserved.
7 | //
8 |
9 | #import "YYFPSLabel.h"
10 | #import "YYWeakProxy.h"
11 |
12 | #define kSize CGSizeMake(55, 20)
13 |
14 | @implementation YYFPSLabel {
15 | CADisplayLink *_link;
16 | NSUInteger _count;
17 | NSTimeInterval _lastTime;
18 | UIFont *_font;
19 | UIFont *_subFont;
20 |
21 | NSTimeInterval _llll;
22 | }
23 |
24 | - (instancetype)initWithFrame:(CGRect)frame {
25 | if (frame.size.width == 0 && frame.size.height == 0) {
26 | frame.size = kSize;
27 | }
28 | self = [super initWithFrame:frame];
29 |
30 | self.layer.cornerRadius = 5;
31 | self.clipsToBounds = YES;
32 | self.textAlignment = NSTextAlignmentCenter;
33 | self.userInteractionEnabled = NO;
34 | self.backgroundColor = [UIColor colorWithWhite:0.000 alpha:0.700];
35 |
36 | _font = [UIFont fontWithName:@"Menlo" size:14];
37 | if (_font) {
38 | _subFont = [UIFont fontWithName:@"Menlo" size:4];
39 | } else {
40 | _font = [UIFont fontWithName:@"Courier" size:14];
41 | _subFont = [UIFont fontWithName:@"Courier" size:4];
42 | }
43 |
44 | // 如果直接用 self 或者 weakSelf,都不能解决循环引用问题
45 |
46 | // 将 timer 的 target 从 self ,变成了中间人 NSProxy
47 | // timer 调用 target 的 selector 时,会被 NSProxy 内部转调用 self 的 selector
48 | _link = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self] selector:@selector(tick:)];
49 | // __weak typeof(self) weakSelf = self;
50 | // _link = [CADisplayLink displayLinkWithTarget:weakSelf selector:@selector(tick:)];
51 | [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
52 |
53 | return self;
54 | }
55 |
56 | - (void)dealloc {
57 | [_link invalidate];
58 | NSLog(@"timer release");
59 | }
60 |
61 | - (CGSize)sizeThatFits:(CGSize)size {
62 | return kSize;
63 | }
64 |
65 | - (void)tick:(CADisplayLink *)link {
66 | if (_lastTime == 0) {
67 | _lastTime = link.timestamp;
68 | return;
69 | }
70 |
71 | _count++;
72 | NSTimeInterval delta = link.timestamp - _lastTime;
73 | if (delta < 1) return;
74 | _lastTime = link.timestamp;
75 | float fps = _count / delta;
76 | _count = 0;
77 |
78 | CGFloat progress = fps / 60.0;
79 | UIColor *color = [UIColor colorWithHue:0.27 * (progress - 0.2) saturation:1 brightness:0.9 alpha:1];
80 |
81 | NSString *text1 = [NSString stringWithFormat:@"%d FPS",(int)round(fps)];
82 | NSLog(@"%@", text1);
83 |
84 |
85 | NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%d FPS",(int)round(fps)]];
86 | [text addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, text.length - 3)];
87 | [text addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(text.length - 3, 3)];
88 | [text addAttribute:NSFontAttributeName value:_font range:NSMakeRange(0, text.length)];
89 | [text addAttribute:NSFontAttributeName value:_subFont range:NSMakeRange(text.length - 4, 1)];
90 | self.attributedText = text;
91 | }
92 |
93 | @end
94 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Vendor/YYFPSLabel/YYWeakProxy.h:
--------------------------------------------------------------------------------
1 | //
2 | // YYWeakProxy.h
3 | // YYKit
4 | //
5 | // Created by ibireme on 14/10/18.
6 | // Copyright (c) 2015 ibireme.
7 | //
8 | // This source code is licensed under the MIT-style license found in the
9 | // LICENSE file in the root directory of this source tree.
10 | //
11 |
12 | /// 注意:如果项目中导入了YYKit框架,就需要删除该类文件。因为YYKit中已经包含了 YYWeakProxy.h 和 YYWeakProxy.m 文件
13 | #import
14 |
15 | /**
16 | A proxy used to hold a weak object.
17 | It can be used to avoid retain cycles, such as the target in NSTimer or CADisplayLink.
18 |
19 | sample code:
20 |
21 | @implementation MyView {
22 | NSTimer *_timer;
23 | }
24 |
25 | - (void)initTimer {
26 | YYWeakProxy *proxy = [YYWeakProxy proxyWithTarget:self];
27 | _timer = [NSTimer timerWithTimeInterval:0.1 target:proxy selector:@selector(tick:) userInfo:nil repeats:YES];
28 | }
29 |
30 | - (void)tick:(NSTimer *)timer {...}
31 | @end
32 | */
33 | @interface YYWeakProxy : NSProxy
34 |
35 | /**
36 | The proxy target.
37 | */
38 | @property (nonatomic, weak, readonly) id target;
39 |
40 | /**
41 | Creates a new weak proxy for target.
42 |
43 | @param target Target object.
44 |
45 | @return A new proxy object.
46 | */
47 | - (instancetype)initWithTarget:(id)target;
48 |
49 | /**
50 | Creates a new weak proxy for target.
51 |
52 | @param target Target object.
53 |
54 | @return A new proxy object.
55 | */
56 | + (instancetype)proxyWithTarget:(id)target;
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/Vendor/YYFPSLabel/YYWeakProxy.m:
--------------------------------------------------------------------------------
1 | //
2 | // YYWeakProxy.m
3 | // YYKit
4 | //
5 | // Created by ibireme on 14/10/18.
6 | // Copyright (c) 2015 ibireme.
7 | //
8 | // This source code is licensed under the MIT-style license found in the
9 | // LICENSE file in the root directory of this source tree.
10 | //
11 |
12 | #import "YYWeakProxy.h"
13 |
14 | /**
15 | 实现的原理: 使用 NSProxy 持有 NSTimer 的 target
16 | 不再用 NSTimer 直接持有 self,就不会导致 timer 对 self 的循环强引用了
17 | */
18 | @implementation YYWeakProxy
19 |
20 | - (instancetype)initWithTarget:(id)target {
21 | _target = target;
22 | return self;
23 | }
24 |
25 | //类方法
26 | + (instancetype)proxyWithTarget:(id)target {
27 | return [[YYWeakProxy alloc] initWithTarget:target];
28 | }
29 |
30 | #pragma mark - private
31 |
32 | - (id)forwardingTargetForSelector:(SEL)selector {
33 | return _target;
34 | }
35 |
36 | #pragma mark - over write
37 |
38 | //重写NSProxy如下两个方法,在处理消息转发时,将消息转发给真正的Target处理
39 | - (void)forwardInvocation:(NSInvocation *)invocation {
40 | void *null = NULL;
41 | [invocation setReturnValue:&null];
42 | }
43 |
44 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
45 | return [NSObject instanceMethodSignatureForSelector:@selector(init)];
46 | }
47 |
48 | - (BOOL)respondsToSelector:(SEL)aSelector {
49 | return [_target respondsToSelector:aSelector];
50 | }
51 |
52 | #pragma mark -
53 |
54 | - (BOOL)isEqual:(id)object {
55 | return [_target isEqual:object];
56 | }
57 |
58 | - (NSUInteger)hash {
59 | return [_target hash];
60 | }
61 |
62 | - (Class)superclass {
63 | return [_target superclass];
64 | }
65 |
66 | - (Class)class {
67 | return [_target class];
68 | }
69 |
70 | - (BOOL)isKindOfClass:(Class)aClass {
71 | return [_target isKindOfClass:aClass];
72 | }
73 |
74 | - (BOOL)isMemberOfClass:(Class)aClass {
75 | return [_target isMemberOfClass:aClass];
76 | }
77 |
78 | - (BOOL)conformsToProtocol:(Protocol *)aProtocol {
79 | return [_target conformsToProtocol:aProtocol];
80 | }
81 |
82 | - (BOOL)isProxy {
83 | return YES;
84 | }
85 |
86 | - (NSString *)description {
87 | return [_target description];
88 | }
89 |
90 | - (NSString *)debugDescription {
91 | return [_target debugDescription];
92 | }
93 |
94 | @end
95 |
--------------------------------------------------------------------------------
/ManageGroup/ManageGroup/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ManageGroup
4 | //
5 | // Created by 任波 on 17/2/22.
6 | // Copyright © 2017年 renbo. 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 |
--------------------------------------------------------------------------------
/ManageGroup/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | target 'ManageGroup' do
5 | # Uncomment this line if you're using Swift or would like to use dynamic frameworks
6 | # use_frameworks!
7 |
8 | # Pods for ManageGroup
9 | pod 'MJExtension', '~> 3.0.13'
10 |
11 | end
12 |
--------------------------------------------------------------------------------
/ManageGroup/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - MJExtension (3.0.13)
3 |
4 | DEPENDENCIES:
5 | - MJExtension (~> 3.0.13)
6 |
7 | SPEC CHECKSUMS:
8 | MJExtension: 5932755f451458eefa24239358817f8d291240c7
9 |
10 | PODFILE CHECKSUM: de965e8f80782d615ad358bb6ce90846fd89d9fa
11 |
12 | COCOAPODS: 1.1.0.beta.1
13 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/MJExtension.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJExtension.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/MJExtensionConst.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJExtensionConst.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/MJFoundation.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJFoundation.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/MJProperty.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJProperty.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/MJPropertyKey.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJPropertyKey.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/MJPropertyType.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJPropertyType.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/NSObject+MJClass.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJClass.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/NSObject+MJCoding.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJCoding.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/NSObject+MJKeyValue.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJKeyValue.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/NSObject+MJProperty.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJProperty.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Private/MJExtension/NSString+MJExtension.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSString+MJExtension.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/MJExtension.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJExtension.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/MJExtensionConst.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJExtensionConst.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/MJFoundation.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJFoundation.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/MJProperty.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJProperty.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/MJPropertyKey.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJPropertyKey.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/MJPropertyType.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/MJPropertyType.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/NSObject+MJClass.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJClass.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/NSObject+MJCoding.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJCoding.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/NSObject+MJKeyValue.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJKeyValue.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/NSObject+MJProperty.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSObject+MJProperty.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/Headers/Public/MJExtension/NSString+MJExtension.h:
--------------------------------------------------------------------------------
1 | ../../../MJExtension/MJExtension/NSString+MJExtension.h
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJExtension.h:
--------------------------------------------------------------------------------
1 | //
2 | // MJExtension.h
3 | // MJExtension
4 | //
5 | // Created by mj on 14-1-15.
6 | // Copyright (c) 2014年 小码哥. All rights reserved.
7 | // 代码地址:https://github.com/CoderMJLee/MJExtension
8 | // 代码地址:http://code4app.com/ios/%E5%AD%97%E5%85%B8-JSON-%E4%B8%8E%E6%A8%A1%E5%9E%8B%E7%9A%84%E8%BD%AC%E6%8D%A2/5339992a933bf062608b4c57
9 |
10 | #import "NSObject+MJCoding.h"
11 | #import "NSObject+MJProperty.h"
12 | #import "NSObject+MJClass.h"
13 | #import "NSObject+MJKeyValue.h"
14 | #import "NSString+MJExtension.h"
15 | #import "MJExtensionConst.h"
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJExtensionConst.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef __MJExtensionConst__H__
3 | #define __MJExtensionConst__H__
4 |
5 | #import
6 |
7 | // 过期
8 | #define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
9 |
10 | // 构建错误
11 | #define MJExtensionBuildError(clazz, msg) \
12 | NSError *error = [NSError errorWithDomain:msg code:250 userInfo:nil]; \
13 | [clazz setMj_error:error];
14 |
15 | // 日志输出
16 | #ifdef DEBUG
17 | #define MJExtensionLog(...) NSLog(__VA_ARGS__)
18 | #else
19 | #define MJExtensionLog(...)
20 | #endif
21 |
22 | /**
23 | * 断言
24 | * @param condition 条件
25 | * @param returnValue 返回值
26 | */
27 | #define MJExtensionAssertError(condition, returnValue, clazz, msg) \
28 | [clazz setMj_error:nil]; \
29 | if ((condition) == NO) { \
30 | MJExtensionBuildError(clazz, msg); \
31 | return returnValue;\
32 | }
33 |
34 | #define MJExtensionAssert2(condition, returnValue) \
35 | if ((condition) == NO) return returnValue;
36 |
37 | /**
38 | * 断言
39 | * @param condition 条件
40 | */
41 | #define MJExtensionAssert(condition) MJExtensionAssert2(condition, )
42 |
43 | /**
44 | * 断言
45 | * @param param 参数
46 | * @param returnValue 返回值
47 | */
48 | #define MJExtensionAssertParamNotNil2(param, returnValue) \
49 | MJExtensionAssert2((param) != nil, returnValue)
50 |
51 | /**
52 | * 断言
53 | * @param param 参数
54 | */
55 | #define MJExtensionAssertParamNotNil(param) MJExtensionAssertParamNotNil2(param, )
56 |
57 | /**
58 | * 打印所有的属性
59 | */
60 | #define MJLogAllIvars \
61 | -(NSString *)description \
62 | { \
63 | return [self mj_keyValues].description; \
64 | }
65 | #define MJExtensionLogAllProperties MJLogAllIvars
66 |
67 | /**
68 | * 类型(属性类型)
69 | */
70 | extern NSString *const MJPropertyTypeInt;
71 | extern NSString *const MJPropertyTypeShort;
72 | extern NSString *const MJPropertyTypeFloat;
73 | extern NSString *const MJPropertyTypeDouble;
74 | extern NSString *const MJPropertyTypeLong;
75 | extern NSString *const MJPropertyTypeLongLong;
76 | extern NSString *const MJPropertyTypeChar;
77 | extern NSString *const MJPropertyTypeBOOL1;
78 | extern NSString *const MJPropertyTypeBOOL2;
79 | extern NSString *const MJPropertyTypePointer;
80 |
81 | extern NSString *const MJPropertyTypeIvar;
82 | extern NSString *const MJPropertyTypeMethod;
83 | extern NSString *const MJPropertyTypeBlock;
84 | extern NSString *const MJPropertyTypeClass;
85 | extern NSString *const MJPropertyTypeSEL;
86 | extern NSString *const MJPropertyTypeId;
87 |
88 | #endif
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJExtensionConst.m:
--------------------------------------------------------------------------------
1 | #ifndef __MJExtensionConst__M__
2 | #define __MJExtensionConst__M__
3 |
4 | #import
5 |
6 | /**
7 | * 成员变量类型(属性类型)
8 | */
9 | NSString *const MJPropertyTypeInt = @"i";
10 | NSString *const MJPropertyTypeShort = @"s";
11 | NSString *const MJPropertyTypeFloat = @"f";
12 | NSString *const MJPropertyTypeDouble = @"d";
13 | NSString *const MJPropertyTypeLong = @"l";
14 | NSString *const MJPropertyTypeLongLong = @"q";
15 | NSString *const MJPropertyTypeChar = @"c";
16 | NSString *const MJPropertyTypeBOOL1 = @"c";
17 | NSString *const MJPropertyTypeBOOL2 = @"b";
18 | NSString *const MJPropertyTypePointer = @"*";
19 |
20 | NSString *const MJPropertyTypeIvar = @"^{objc_ivar=}";
21 | NSString *const MJPropertyTypeMethod = @"^{objc_method=}";
22 | NSString *const MJPropertyTypeBlock = @"@?";
23 | NSString *const MJPropertyTypeClass = @"#";
24 | NSString *const MJPropertyTypeSEL = @":";
25 | NSString *const MJPropertyTypeId = @"@";
26 |
27 | #endif
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJFoundation.h:
--------------------------------------------------------------------------------
1 | //
2 | // MJFoundation.h
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 14/7/16.
6 | // Copyright (c) 2014年 小码哥. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MJFoundation : NSObject
12 | + (BOOL)isClassFromFoundation:(Class)c;
13 | @end
14 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJFoundation.m:
--------------------------------------------------------------------------------
1 | //
2 | // MJFoundation.m
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 14/7/16.
6 | // Copyright (c) 2014年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "MJFoundation.h"
10 | #import "MJExtensionConst.h"
11 | #import
12 |
13 | static NSSet *foundationClasses_;
14 |
15 | @implementation MJFoundation
16 |
17 | + (NSSet *)foundationClasses
18 | {
19 | if (foundationClasses_ == nil) {
20 | // 集合中没有NSObject,因为几乎所有的类都是继承自NSObject,具体是不是NSObject需要特殊判断
21 | foundationClasses_ = [NSSet setWithObjects:
22 | [NSURL class],
23 | [NSDate class],
24 | [NSValue class],
25 | [NSData class],
26 | [NSError class],
27 | [NSArray class],
28 | [NSDictionary class],
29 | [NSString class],
30 | [NSAttributedString class], nil];
31 | }
32 | return foundationClasses_;
33 | }
34 |
35 | + (BOOL)isClassFromFoundation:(Class)c
36 | {
37 | if (c == [NSObject class] || c == [NSManagedObject class]) return YES;
38 |
39 | __block BOOL result = NO;
40 | [[self foundationClasses] enumerateObjectsUsingBlock:^(Class foundationClass, BOOL *stop) {
41 | if ([c isSubclassOfClass:foundationClass]) {
42 | result = YES;
43 | *stop = YES;
44 | }
45 | }];
46 | return result;
47 | }
48 | @end
49 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJProperty.h:
--------------------------------------------------------------------------------
1 | //
2 | // MJProperty.h
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/4/17.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | // 包装一个成员属性
8 |
9 | #import
10 | #import
11 | #import "MJPropertyType.h"
12 | #import "MJPropertyKey.h"
13 |
14 | /**
15 | * 包装一个成员
16 | */
17 | @interface MJProperty : NSObject
18 | /** 成员属性 */
19 | @property (nonatomic, assign) objc_property_t property;
20 | /** 成员属性的名字 */
21 | @property (nonatomic, readonly) NSString *name;
22 |
23 | /** 成员属性的类型 */
24 | @property (nonatomic, readonly) MJPropertyType *type;
25 | /** 成员属性来源于哪个类(可能是父类) */
26 | @property (nonatomic, assign) Class srcClass;
27 |
28 | /**** 同一个成员属性 - 父类和子类的行为可能不一致(originKey、propertyKeys、objectClassInArray) ****/
29 | /** 设置最原始的key */
30 | - (void)setOriginKey:(id)originKey forClass:(Class)c;
31 | /** 对应着字典中的多级key(里面存放的数组,数组里面都是MJPropertyKey对象) */
32 | - (NSArray *)propertyKeysForClass:(Class)c;
33 |
34 | /** 模型数组中的模型类型 */
35 | - (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c;
36 | - (Class)objectClassInArrayForClass:(Class)c;
37 | /**** 同一个成员变量 - 父类和子类的行为可能不一致(key、keys、objectClassInArray) ****/
38 |
39 | /**
40 | * 设置object的成员变量值
41 | */
42 | - (void)setValue:(id)value forObject:(id)object;
43 | /**
44 | * 得到object的成员属性值
45 | */
46 | - (id)valueForObject:(id)object;
47 |
48 | /**
49 | * 初始化
50 | */
51 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property;
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJProperty.m:
--------------------------------------------------------------------------------
1 | //
2 | // MJProperty.m
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/4/17.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "MJProperty.h"
10 | #import "MJFoundation.h"
11 | #import "MJExtensionConst.h"
12 | #import
13 |
14 | @interface MJProperty()
15 | @property (strong, nonatomic) NSMutableDictionary *propertyKeysDict;
16 | @property (strong, nonatomic) NSMutableDictionary *objectClassInArrayDict;
17 | @end
18 |
19 | @implementation MJProperty
20 |
21 | #pragma mark - 初始化
22 | - (instancetype)init
23 | {
24 | if (self = [super init]) {
25 | _propertyKeysDict = [NSMutableDictionary dictionary];
26 | _objectClassInArrayDict = [NSMutableDictionary dictionary];
27 | }
28 | return self;
29 | }
30 |
31 | #pragma mark - 缓存
32 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property
33 | {
34 | MJProperty *propertyObj = objc_getAssociatedObject(self, property);
35 | if (propertyObj == nil) {
36 | propertyObj = [[self alloc] init];
37 | propertyObj.property = property;
38 | objc_setAssociatedObject(self, property, propertyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
39 | }
40 | return propertyObj;
41 | }
42 |
43 | #pragma mark - 公共方法
44 | - (void)setProperty:(objc_property_t)property
45 | {
46 | _property = property;
47 |
48 | MJExtensionAssertParamNotNil(property);
49 |
50 | // 1.属性名
51 | _name = @(property_getName(property));
52 |
53 | // 2.成员类型
54 | NSString *attrs = @(property_getAttributes(property));
55 | NSUInteger dotLoc = [attrs rangeOfString:@","].location;
56 | NSString *code = nil;
57 | NSUInteger loc = 1;
58 | if (dotLoc == NSNotFound) { // 没有,
59 | code = [attrs substringFromIndex:loc];
60 | } else {
61 | code = [attrs substringWithRange:NSMakeRange(loc, dotLoc - loc)];
62 | }
63 | _type = [MJPropertyType cachedTypeWithCode:code];
64 | }
65 |
66 | /**
67 | * 获得成员变量的值
68 | */
69 | - (id)valueForObject:(id)object
70 | {
71 | if (self.type.KVCDisabled) return [NSNull null];
72 | return [object valueForKey:self.name];
73 | }
74 |
75 | /**
76 | * 设置成员变量的值
77 | */
78 | - (void)setValue:(id)value forObject:(id)object
79 | {
80 | if (self.type.KVCDisabled || value == nil) return;
81 | [object setValue:value forKey:self.name];
82 | }
83 |
84 | /**
85 | * 通过字符串key创建对应的keys
86 | */
87 | - (NSArray *)propertyKeysWithStringKey:(NSString *)stringKey
88 | {
89 | if (stringKey.length == 0) return nil;
90 |
91 | NSMutableArray *propertyKeys = [NSMutableArray array];
92 | // 如果有多级映射
93 | NSArray *oldKeys = [stringKey componentsSeparatedByString:@"."];
94 |
95 | for (NSString *oldKey in oldKeys) {
96 | NSUInteger start = [oldKey rangeOfString:@"["].location;
97 | if (start != NSNotFound) { // 有索引的key
98 | NSString *prefixKey = [oldKey substringToIndex:start];
99 | NSString *indexKey = prefixKey;
100 | if (prefixKey.length) {
101 | MJPropertyKey *propertyKey = [[MJPropertyKey alloc] init];
102 | propertyKey.name = prefixKey;
103 | [propertyKeys addObject:propertyKey];
104 |
105 | indexKey = [oldKey stringByReplacingOccurrencesOfString:prefixKey withString:@""];
106 | }
107 |
108 | /** 解析索引 **/
109 | // 元素
110 | NSArray *cmps = [[indexKey stringByReplacingOccurrencesOfString:@"[" withString:@""] componentsSeparatedByString:@"]"];
111 | for (NSInteger i = 0; i
10 |
11 | typedef enum {
12 | MJPropertyKeyTypeDictionary = 0, // 字典的key
13 | MJPropertyKeyTypeArray // 数组的key
14 | } MJPropertyKeyType;
15 |
16 | /**
17 | * 属性的key
18 | */
19 | @interface MJPropertyKey : NSObject
20 | /** key的名字 */
21 | @property (copy, nonatomic) NSString *name;
22 | /** key的种类,可能是@"10",可能是@"age" */
23 | @property (assign, nonatomic) MJPropertyKeyType type;
24 |
25 | /**
26 | * 根据当前的key,也就是name,从object(字典或者数组)中取值
27 | */
28 | - (id)valueInObject:(id)object;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJPropertyKey.m:
--------------------------------------------------------------------------------
1 | //
2 | // MJPropertyKey.m
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/8/11.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "MJPropertyKey.h"
10 |
11 | @implementation MJPropertyKey
12 |
13 | - (id)valueInObject:(id)object
14 | {
15 | if ([object isKindOfClass:[NSDictionary class]] && self.type == MJPropertyKeyTypeDictionary) {
16 | return object[self.name];
17 | } else if ([object isKindOfClass:[NSArray class]] && self.type == MJPropertyKeyTypeArray) {
18 | NSArray *array = object;
19 | NSUInteger index = self.name.intValue;
20 | if (index < array.count) return array[index];
21 | return nil;
22 | }
23 | return nil;
24 | }
25 | @end
26 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJPropertyType.h:
--------------------------------------------------------------------------------
1 | //
2 | // MJPropertyType.h
3 | // MJExtension
4 | //
5 | // Created by mj on 14-1-15.
6 | // Copyright (c) 2014年 小码哥. All rights reserved.
7 | // 包装一种类型
8 |
9 | #import
10 |
11 | /**
12 | * 包装一种类型
13 | */
14 | @interface MJPropertyType : NSObject
15 | /** 类型标识符 */
16 | @property (nonatomic, copy) NSString *code;
17 |
18 | /** 是否为id类型 */
19 | @property (nonatomic, readonly, getter=isIdType) BOOL idType;
20 |
21 | /** 是否为基本数字类型:int、float等 */
22 | @property (nonatomic, readonly, getter=isNumberType) BOOL numberType;
23 |
24 | /** 是否为BOOL类型 */
25 | @property (nonatomic, readonly, getter=isBoolType) BOOL boolType;
26 |
27 | /** 对象类型(如果是基本数据类型,此值为nil) */
28 | @property (nonatomic, readonly) Class typeClass;
29 |
30 | /** 类型是否来自于Foundation框架,比如NSString、NSArray */
31 | @property (nonatomic, readonly, getter = isFromFoundation) BOOL fromFoundation;
32 | /** 类型是否不支持KVC */
33 | @property (nonatomic, readonly, getter = isKVCDisabled) BOOL KVCDisabled;
34 |
35 | /**
36 | * 获得缓存的类型对象
37 | */
38 | + (instancetype)cachedTypeWithCode:(NSString *)code;
39 | @end
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/MJPropertyType.m:
--------------------------------------------------------------------------------
1 | //
2 | // MJPropertyType.m
3 | // MJExtension
4 | //
5 | // Created by mj on 14-1-15.
6 | // Copyright (c) 2014年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "MJPropertyType.h"
10 | #import "MJExtension.h"
11 | #import "MJFoundation.h"
12 | #import "MJExtensionConst.h"
13 |
14 | @implementation MJPropertyType
15 |
16 | static NSMutableDictionary *types_;
17 | + (void)initialize
18 | {
19 | types_ = [NSMutableDictionary dictionary];
20 | }
21 |
22 | + (instancetype)cachedTypeWithCode:(NSString *)code
23 | {
24 | MJExtensionAssertParamNotNil2(code, nil);
25 | @synchronized (self) {
26 | MJPropertyType *type = types_[code];
27 | if (type == nil) {
28 | type = [[self alloc] init];
29 | type.code = code;
30 | types_[code] = type;
31 | }
32 | return type;
33 | }
34 | }
35 |
36 | #pragma mark - 公共方法
37 | - (void)setCode:(NSString *)code
38 | {
39 | _code = code;
40 |
41 | MJExtensionAssertParamNotNil(code);
42 |
43 | if ([code isEqualToString:MJPropertyTypeId]) {
44 | _idType = YES;
45 | } else if (code.length == 0) {
46 | _KVCDisabled = YES;
47 | } else if (code.length > 3 && [code hasPrefix:@"@\""]) {
48 | // 去掉@"和",截取中间的类型名称
49 | _code = [code substringWithRange:NSMakeRange(2, code.length - 3)];
50 | _typeClass = NSClassFromString(_code);
51 | _fromFoundation = [MJFoundation isClassFromFoundation:_typeClass];
52 | _numberType = [_typeClass isSubclassOfClass:[NSNumber class]];
53 |
54 | } else if ([code isEqualToString:MJPropertyTypeSEL] ||
55 | [code isEqualToString:MJPropertyTypeIvar] ||
56 | [code isEqualToString:MJPropertyTypeMethod]) {
57 | _KVCDisabled = YES;
58 | }
59 |
60 | // 是否为数字类型
61 | NSString *lowerCode = _code.lowercaseString;
62 | NSArray *numberTypes = @[MJPropertyTypeInt, MJPropertyTypeShort, MJPropertyTypeBOOL1, MJPropertyTypeBOOL2, MJPropertyTypeFloat, MJPropertyTypeDouble, MJPropertyTypeLong, MJPropertyTypeLongLong, MJPropertyTypeChar];
63 | if ([numberTypes containsObject:lowerCode]) {
64 | _numberType = YES;
65 |
66 | if ([lowerCode isEqualToString:MJPropertyTypeBOOL1]
67 | || [lowerCode isEqualToString:MJPropertyTypeBOOL2]) {
68 | _boolType = YES;
69 | }
70 | }
71 | }
72 | @end
73 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJClass.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJClass.h
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/8/11.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * 遍历所有类的block(父类)
13 | */
14 | typedef void (^MJClassesEnumeration)(Class c, BOOL *stop);
15 |
16 | /** 这个数组中的属性名才会进行字典和模型的转换 */
17 | typedef NSArray * (^MJAllowedPropertyNames)();
18 | /** 这个数组中的属性名才会进行归档 */
19 | typedef NSArray * (^MJAllowedCodingPropertyNames)();
20 |
21 | /** 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */
22 | typedef NSArray * (^MJIgnoredPropertyNames)();
23 | /** 这个数组中的属性名将会被忽略:不进行归档 */
24 | typedef NSArray * (^MJIgnoredCodingPropertyNames)();
25 |
26 | /**
27 | * 类相关的扩展
28 | */
29 | @interface NSObject (MJClass)
30 | /**
31 | * 遍历所有的类
32 | */
33 | + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration;
34 | + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration;
35 |
36 | #pragma mark - 属性白名单配置
37 | /**
38 | * 这个数组中的属性名才会进行字典和模型的转换
39 | *
40 | * @param allowedPropertyNames 这个数组中的属性名才会进行字典和模型的转换
41 | */
42 | + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames;
43 |
44 | /**
45 | * 这个数组中的属性名才会进行字典和模型的转换
46 | */
47 | + (NSMutableArray *)mj_totalAllowedPropertyNames;
48 |
49 | #pragma mark - 属性黑名单配置
50 | /**
51 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换
52 | *
53 | * @param ignoredPropertyNames 这个数组中的属性名将会被忽略:不进行字典和模型的转换
54 | */
55 | + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames;
56 |
57 | /**
58 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换
59 | */
60 | + (NSMutableArray *)mj_totalIgnoredPropertyNames;
61 |
62 | #pragma mark - 归档属性白名单配置
63 | /**
64 | * 这个数组中的属性名才会进行归档
65 | *
66 | * @param allowedCodingPropertyNames 这个数组中的属性名才会进行归档
67 | */
68 | + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames;
69 |
70 | /**
71 | * 这个数组中的属性名才会进行字典和模型的转换
72 | */
73 | + (NSMutableArray *)mj_totalAllowedCodingPropertyNames;
74 |
75 | #pragma mark - 归档属性黑名单配置
76 | /**
77 | * 这个数组中的属性名将会被忽略:不进行归档
78 | *
79 | * @param ignoredCodingPropertyNames 这个数组中的属性名将会被忽略:不进行归档
80 | */
81 | + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames;
82 |
83 | /**
84 | * 这个数组中的属性名将会被忽略:不进行归档
85 | */
86 | + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames;
87 |
88 | #pragma mark - 内部使用
89 | + (void)mj_setupBlockReturnValue:(id (^)())block key:(const char *)key;
90 | @end
91 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJClass.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJClass.m
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/8/11.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "NSObject+MJClass.h"
10 | #import "NSObject+MJCoding.h"
11 | #import "NSObject+MJKeyValue.h"
12 | #import "MJFoundation.h"
13 | #import
14 |
15 | static const char MJAllowedPropertyNamesKey = '\0';
16 | static const char MJIgnoredPropertyNamesKey = '\0';
17 | static const char MJAllowedCodingPropertyNamesKey = '\0';
18 | static const char MJIgnoredCodingPropertyNamesKey = '\0';
19 |
20 | static NSMutableDictionary *allowedPropertyNamesDict_;
21 | static NSMutableDictionary *ignoredPropertyNamesDict_;
22 | static NSMutableDictionary *allowedCodingPropertyNamesDict_;
23 | static NSMutableDictionary *ignoredCodingPropertyNamesDict_;
24 |
25 | @implementation NSObject (MJClass)
26 |
27 | + (void)load
28 | {
29 | allowedPropertyNamesDict_ = [NSMutableDictionary dictionary];
30 | ignoredPropertyNamesDict_ = [NSMutableDictionary dictionary];
31 | allowedCodingPropertyNamesDict_ = [NSMutableDictionary dictionary];
32 | ignoredCodingPropertyNamesDict_ = [NSMutableDictionary dictionary];
33 | }
34 |
35 | + (NSMutableDictionary *)dictForKey:(const void *)key
36 | {
37 | @synchronized (self) {
38 | if (key == &MJAllowedPropertyNamesKey) return allowedPropertyNamesDict_;
39 | if (key == &MJIgnoredPropertyNamesKey) return ignoredPropertyNamesDict_;
40 | if (key == &MJAllowedCodingPropertyNamesKey) return allowedCodingPropertyNamesDict_;
41 | if (key == &MJIgnoredCodingPropertyNamesKey) return ignoredCodingPropertyNamesDict_;
42 | return nil;
43 | }
44 | }
45 |
46 | + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration
47 | {
48 | // 1.没有block就直接返回
49 | if (enumeration == nil) return;
50 |
51 | // 2.停止遍历的标记
52 | BOOL stop = NO;
53 |
54 | // 3.当前正在遍历的类
55 | Class c = self;
56 |
57 | // 4.开始遍历每一个类
58 | while (c && !stop) {
59 | // 4.1.执行操作
60 | enumeration(c, &stop);
61 |
62 | // 4.2.获得父类
63 | c = class_getSuperclass(c);
64 |
65 | if ([MJFoundation isClassFromFoundation:c]) break;
66 | }
67 | }
68 |
69 | + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration
70 | {
71 | // 1.没有block就直接返回
72 | if (enumeration == nil) return;
73 |
74 | // 2.停止遍历的标记
75 | BOOL stop = NO;
76 |
77 | // 3.当前正在遍历的类
78 | Class c = self;
79 |
80 | // 4.开始遍历每一个类
81 | while (c && !stop) {
82 | // 4.1.执行操作
83 | enumeration(c, &stop);
84 |
85 | // 4.2.获得父类
86 | c = class_getSuperclass(c);
87 | }
88 | }
89 |
90 | #pragma mark - 属性黑名单配置
91 | + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames
92 | {
93 | [self mj_setupBlockReturnValue:ignoredPropertyNames key:&MJIgnoredPropertyNamesKey];
94 | }
95 |
96 | + (NSMutableArray *)mj_totalIgnoredPropertyNames
97 | {
98 | return [self mj_totalObjectsWithSelector:@selector(mj_ignoredPropertyNames) key:&MJIgnoredPropertyNamesKey];
99 | }
100 |
101 | #pragma mark - 归档属性黑名单配置
102 | + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames
103 | {
104 | [self mj_setupBlockReturnValue:ignoredCodingPropertyNames key:&MJIgnoredCodingPropertyNamesKey];
105 | }
106 |
107 | + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames
108 | {
109 | return [self mj_totalObjectsWithSelector:@selector(mj_ignoredCodingPropertyNames) key:&MJIgnoredCodingPropertyNamesKey];
110 | }
111 |
112 | #pragma mark - 属性白名单配置
113 | + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames;
114 | {
115 | [self mj_setupBlockReturnValue:allowedPropertyNames key:&MJAllowedPropertyNamesKey];
116 | }
117 |
118 | + (NSMutableArray *)mj_totalAllowedPropertyNames
119 | {
120 | return [self mj_totalObjectsWithSelector:@selector(mj_allowedPropertyNames) key:&MJAllowedPropertyNamesKey];
121 | }
122 |
123 | #pragma mark - 归档属性白名单配置
124 | + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames
125 | {
126 | [self mj_setupBlockReturnValue:allowedCodingPropertyNames key:&MJAllowedCodingPropertyNamesKey];
127 | }
128 |
129 | + (NSMutableArray *)mj_totalAllowedCodingPropertyNames
130 | {
131 | return [self mj_totalObjectsWithSelector:@selector(mj_allowedCodingPropertyNames) key:&MJAllowedCodingPropertyNamesKey];
132 | }
133 | #pragma mark - block和方法处理:存储block的返回值
134 | + (void)mj_setupBlockReturnValue:(id (^)())block key:(const char *)key
135 | {
136 | if (block) {
137 | objc_setAssociatedObject(self, key, block(), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
138 | } else {
139 | objc_setAssociatedObject(self, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
140 | }
141 |
142 | // 清空数据
143 | [[self dictForKey:key] removeAllObjects];
144 | }
145 |
146 | + (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)key
147 | {
148 | NSMutableArray *array = [self dictForKey:key][NSStringFromClass(self)];
149 | if (array) return array;
150 |
151 | // 创建、存储
152 | [self dictForKey:key][NSStringFromClass(self)] = array = [NSMutableArray array];
153 |
154 | if ([self respondsToSelector:selector]) {
155 | #pragma clang diagnostic push
156 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
157 | NSArray *subArray = [self performSelector:selector];
158 | #pragma clang diagnostic pop
159 | if (subArray) {
160 | [array addObjectsFromArray:subArray];
161 | }
162 | }
163 |
164 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
165 | NSArray *subArray = objc_getAssociatedObject(c, key);
166 | [array addObjectsFromArray:subArray];
167 | }];
168 | return array;
169 | }
170 | @end
171 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJCoding.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJCoding.h
3 | // MJExtension
4 | //
5 | // Created by mj on 14-1-15.
6 | // Copyright (c) 2014年 小码哥. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MJExtensionConst.h"
11 |
12 | /**
13 | * Codeing协议
14 | */
15 | @protocol MJCoding
16 | @optional
17 | /**
18 | * 这个数组中的属性名才会进行归档
19 | */
20 | + (NSArray *)mj_allowedCodingPropertyNames;
21 | /**
22 | * 这个数组中的属性名将会被忽略:不进行归档
23 | */
24 | + (NSArray *)mj_ignoredCodingPropertyNames;
25 | @end
26 |
27 | @interface NSObject (MJCoding)
28 | /**
29 | * 解码(从文件中解析对象)
30 | */
31 | - (void)mj_decode:(NSCoder *)decoder;
32 | /**
33 | * 编码(将对象写入文件中)
34 | */
35 | - (void)mj_encode:(NSCoder *)encoder;
36 | @end
37 |
38 | /**
39 | 归档的实现
40 | */
41 | #define MJCodingImplementation \
42 | - (id)initWithCoder:(NSCoder *)decoder \
43 | { \
44 | if (self = [super init]) { \
45 | [self mj_decode:decoder]; \
46 | } \
47 | return self; \
48 | } \
49 | \
50 | - (void)encodeWithCoder:(NSCoder *)encoder \
51 | { \
52 | [self mj_encode:encoder]; \
53 | }
54 |
55 | #define MJExtensionCodingImplementation MJCodingImplementation
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJCoding.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJCoding.m
3 | // MJExtension
4 | //
5 | // Created by mj on 14-1-15.
6 | // Copyright (c) 2014年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "NSObject+MJCoding.h"
10 | #import "NSObject+MJClass.h"
11 | #import "NSObject+MJProperty.h"
12 | #import "MJProperty.h"
13 |
14 | @implementation NSObject (MJCoding)
15 |
16 | - (void)mj_encode:(NSCoder *)encoder
17 | {
18 | Class clazz = [self class];
19 |
20 | NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames];
21 | NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames];
22 |
23 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
24 | // 检测是否被忽略
25 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return;
26 | if ([ignoredCodingPropertyNames containsObject:property.name]) return;
27 |
28 | id value = [property valueForObject:self];
29 | if (value == nil) return;
30 | [encoder encodeObject:value forKey:property.name];
31 | }];
32 | }
33 |
34 | - (void)mj_decode:(NSCoder *)decoder
35 | {
36 | Class clazz = [self class];
37 |
38 | NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames];
39 | NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames];
40 |
41 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
42 | // 检测是否被忽略
43 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return;
44 | if ([ignoredCodingPropertyNames containsObject:property.name]) return;
45 |
46 | id value = [decoder decodeObjectForKey:property.name];
47 | if (value == nil) { // 兼容以前的MJExtension版本
48 | value = [decoder decodeObjectForKey:[@"_" stringByAppendingString:property.name]];
49 | }
50 | if (value == nil) return;
51 | [property setValue:value forObject:self];
52 | }];
53 | }
54 | @end
55 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJKeyValue.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJKeyValue.h
3 | // MJExtension
4 | //
5 | // Created by mj on 13-8-24.
6 | // Copyright (c) 2013年 小码哥. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MJExtensionConst.h"
11 | #import
12 | #import "MJProperty.h"
13 |
14 | /**
15 | * KeyValue协议
16 | */
17 | @protocol MJKeyValue
18 | @optional
19 | /**
20 | * 只有这个数组中的属性名才允许进行字典和模型的转换
21 | */
22 | + (NSArray *)mj_allowedPropertyNames;
23 |
24 | /**
25 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换
26 | */
27 | + (NSArray *)mj_ignoredPropertyNames;
28 |
29 | /**
30 | * 将属性名换为其他key去字典中取值
31 | *
32 | * @return 字典中的key是属性名,value是从字典中取值用的key
33 | */
34 | + (NSDictionary *)mj_replacedKeyFromPropertyName;
35 |
36 | /**
37 | * 将属性名换为其他key去字典中取值
38 | *
39 | * @return 从字典中取值用的key
40 | */
41 | + (id)mj_replacedKeyFromPropertyName121:(NSString *)propertyName;
42 |
43 | /**
44 | * 数组中需要转换的模型类
45 | *
46 | * @return 字典中的key是数组属性名,value是数组中存放模型的Class(Class类型或者NSString类型)
47 | */
48 | + (NSDictionary *)mj_objectClassInArray;
49 |
50 | /**
51 | * 旧值换新值,用于过滤字典中的值
52 | *
53 | * @param oldValue 旧值
54 | *
55 | * @return 新值
56 | */
57 | - (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property;
58 |
59 | /**
60 | * 当字典转模型完毕时调用
61 | */
62 | - (void)mj_keyValuesDidFinishConvertingToObject;
63 |
64 | /**
65 | * 当模型转字典完毕时调用
66 | */
67 | - (void)mj_objectDidFinishConvertingToKeyValues;
68 | @end
69 |
70 | @interface NSObject (MJKeyValue)
71 | #pragma mark - 类方法
72 | /**
73 | * 字典转模型过程中遇到的错误
74 | */
75 | + (NSError *)mj_error;
76 |
77 | /**
78 | * 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来)
79 | */
80 | + (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference;
81 |
82 | #pragma mark - 对象方法
83 | /**
84 | * 将字典的键值对转成模型属性
85 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString)
86 | */
87 | - (instancetype)mj_setKeyValues:(id)keyValues;
88 |
89 | /**
90 | * 将字典的键值对转成模型属性
91 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString)
92 | * @param context CoreData上下文
93 | */
94 | - (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;
95 |
96 | /**
97 | * 将模型转成字典
98 | * @return 字典
99 | */
100 | - (NSMutableDictionary *)mj_keyValues;
101 | - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys;
102 | - (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys;
103 |
104 | /**
105 | * 通过模型数组来创建一个字典数组
106 | * @param objectArray 模型数组
107 | * @return 字典数组
108 | */
109 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray;
110 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys;
111 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys;
112 |
113 | #pragma mark - 字典转模型
114 | /**
115 | * 通过字典来创建一个模型
116 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString)
117 | * @return 新建的对象
118 | */
119 | + (instancetype)mj_objectWithKeyValues:(id)keyValues;
120 |
121 | /**
122 | * 通过字典来创建一个CoreData模型
123 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString)
124 | * @param context CoreData上下文
125 | * @return 新建的对象
126 | */
127 | + (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;
128 |
129 | /**
130 | * 通过plist来创建一个模型
131 | * @param filename 文件名(仅限于mainBundle中的文件)
132 | * @return 新建的对象
133 | */
134 | + (instancetype)mj_objectWithFilename:(NSString *)filename;
135 |
136 | /**
137 | * 通过plist来创建一个模型
138 | * @param file 文件全路径
139 | * @return 新建的对象
140 | */
141 | + (instancetype)mj_objectWithFile:(NSString *)file;
142 |
143 | #pragma mark - 字典数组转模型数组
144 | /**
145 | * 通过字典数组来创建一个模型数组
146 | * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString)
147 | * @return 模型数组
148 | */
149 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray;
150 |
151 | /**
152 | * 通过字典数组来创建一个模型数组
153 | * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString)
154 | * @param context CoreData上下文
155 | * @return 模型数组
156 | */
157 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context;
158 |
159 | /**
160 | * 通过plist来创建一个模型数组
161 | * @param filename 文件名(仅限于mainBundle中的文件)
162 | * @return 模型数组
163 | */
164 | + (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename;
165 |
166 | /**
167 | * 通过plist来创建一个模型数组
168 | * @param file 文件全路径
169 | * @return 模型数组
170 | */
171 | + (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file;
172 |
173 | #pragma mark - 转换为JSON
174 | /**
175 | * 转换为JSON Data
176 | */
177 | - (NSData *)mj_JSONData;
178 | /**
179 | * 转换为字典或者数组
180 | */
181 | - (id)mj_JSONObject;
182 | /**
183 | * 转换为JSON 字符串
184 | */
185 | - (NSString *)mj_JSONString;
186 | @end
187 |
188 | @interface NSObject (MJKeyValueDeprecated_v_2_5_16)
189 | - (instancetype)setKeyValues:(id)keyValue MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
190 | - (instancetype)setKeyValues:(id)keyValues error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
191 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
192 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
193 | + (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
194 | - (NSMutableDictionary *)keyValues MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
195 | - (NSMutableDictionary *)keyValuesWithError:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
196 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
197 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
198 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
199 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
200 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
201 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
202 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
203 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
204 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
205 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
206 | + (instancetype)objectWithKeyValues:(id)keyValues MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
207 | + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
208 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
209 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
210 | + (instancetype)objectWithFilename:(NSString *)filename MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
211 | + (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
212 | + (instancetype)objectWithFile:(NSString *)file MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
213 | + (instancetype)objectWithFile:(NSString *)file error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
214 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
215 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
216 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
217 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
218 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
219 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
220 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
221 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
222 | - (NSData *)JSONData MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
223 | - (id)JSONObject MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
224 | - (NSString *)JSONString MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
225 | @end
226 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJKeyValue.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJKeyValue.m
3 | // MJExtension
4 | //
5 | // Created by mj on 13-8-24.
6 | // Copyright (c) 2013年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "NSObject+MJKeyValue.h"
10 | #import "NSObject+MJProperty.h"
11 | #import "NSString+MJExtension.h"
12 | #import "MJProperty.h"
13 | #import "MJPropertyType.h"
14 | #import "MJExtensionConst.h"
15 | #import "MJFoundation.h"
16 | #import "NSString+MJExtension.h"
17 | #import "NSObject+MJClass.h"
18 |
19 | @implementation NSObject (MJKeyValue)
20 |
21 | #pragma mark - 错误
22 | static const char MJErrorKey = '\0';
23 | + (NSError *)mj_error
24 | {
25 | return objc_getAssociatedObject(self, &MJErrorKey);
26 | }
27 |
28 | + (void)setMj_error:(NSError *)error
29 | {
30 | objc_setAssociatedObject(self, &MJErrorKey, error, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
31 | }
32 |
33 | #pragma mark - 模型 -> 字典时的参考
34 | /** 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来) */
35 | static const char MJReferenceReplacedKeyWhenCreatingKeyValuesKey = '\0';
36 |
37 | + (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference
38 | {
39 | objc_setAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey, @(reference), OBJC_ASSOCIATION_ASSIGN);
40 | }
41 |
42 | + (BOOL)mj_isReferenceReplacedKeyWhenCreatingKeyValues
43 | {
44 | __block id value = objc_getAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey);
45 | if (!value) {
46 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
47 | value = objc_getAssociatedObject(c, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey);
48 |
49 | if (value) *stop = YES;
50 | }];
51 | }
52 | return [value boolValue];
53 | }
54 |
55 | #pragma mark - --常用的对象--
56 | static NSNumberFormatter *numberFormatter_;
57 | + (void)load
58 | {
59 | numberFormatter_ = [[NSNumberFormatter alloc] init];
60 |
61 | // 默认设置
62 | [self mj_referenceReplacedKeyWhenCreatingKeyValues:YES];
63 | }
64 |
65 | #pragma mark - --公共方法--
66 | #pragma mark - 字典 -> 模型
67 | - (instancetype)mj_setKeyValues:(id)keyValues
68 | {
69 | return [self mj_setKeyValues:keyValues context:nil];
70 | }
71 |
72 | /**
73 | 核心代码:
74 | */
75 | - (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
76 | {
77 | // 获得JSON对象
78 | keyValues = [keyValues mj_JSONObject];
79 |
80 | MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], self, [self class], @"keyValues参数不是一个字典");
81 |
82 | Class clazz = [self class];
83 | NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames];
84 | NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames];
85 |
86 | //通过封装的方法回调一个通过运行时编写的,用于返回属性列表的方法。
87 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
88 | @try {
89 | // 0.检测是否被忽略
90 | if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
91 | if ([ignoredPropertyNames containsObject:property.name]) return;
92 |
93 | // 1.取出属性值
94 | id value;
95 | NSArray *propertyKeyses = [property propertyKeysForClass:clazz];
96 | for (NSArray *propertyKeys in propertyKeyses) {
97 | value = keyValues;
98 | for (MJPropertyKey *propertyKey in propertyKeys) {
99 | value = [propertyKey valueInObject:value];
100 | }
101 | if (value) break;
102 | }
103 |
104 | // 值的过滤
105 | id newValue = [clazz mj_getNewValueFromObject:self oldValue:value property:property];
106 | if (newValue != value) { // 有过滤后的新值
107 | [property setValue:newValue forObject:self];
108 | return;
109 | }
110 |
111 | // 如果没有值,就直接返回
112 | if (!value || value == [NSNull null]) return;
113 |
114 | // 2.复杂处理
115 | MJPropertyType *type = property.type;
116 | Class propertyClass = type.typeClass;
117 | Class objectClass = [property objectClassInArrayForClass:[self class]];
118 |
119 | // 不可变 -> 可变处理
120 | if (propertyClass == [NSMutableArray class] && [value isKindOfClass:[NSArray class]]) {
121 | value = [NSMutableArray arrayWithArray:value];
122 | } else if (propertyClass == [NSMutableDictionary class] && [value isKindOfClass:[NSDictionary class]]) {
123 | value = [NSMutableDictionary dictionaryWithDictionary:value];
124 | } else if (propertyClass == [NSMutableString class] && [value isKindOfClass:[NSString class]]) {
125 | value = [NSMutableString stringWithString:value];
126 | } else if (propertyClass == [NSMutableData class] && [value isKindOfClass:[NSData class]]) {
127 | value = [NSMutableData dataWithData:value];
128 | }
129 |
130 | if (!type.isFromFoundation && propertyClass) { // 模型属性
131 | value = [propertyClass mj_objectWithKeyValues:value context:context];
132 | } else if (objectClass) {
133 | if (objectClass == [NSURL class] && [value isKindOfClass:[NSArray class]]) {
134 | // string array -> url array
135 | NSMutableArray *urlArray = [NSMutableArray array];
136 | for (NSString *string in value) {
137 | if (![string isKindOfClass:[NSString class]]) continue;
138 | [urlArray addObject:string.mj_url];
139 | }
140 | value = urlArray;
141 | } else { // 字典数组-->模型数组
142 | value = [objectClass mj_objectArrayWithKeyValuesArray:value context:context];
143 | }
144 | } else {
145 | if (propertyClass == [NSString class]) {
146 | if ([value isKindOfClass:[NSNumber class]]) {
147 | // NSNumber -> NSString
148 | value = [value description];
149 | } else if ([value isKindOfClass:[NSURL class]]) {
150 | // NSURL -> NSString
151 | value = [value absoluteString];
152 | }
153 | } else if ([value isKindOfClass:[NSString class]]) {
154 | if (propertyClass == [NSURL class]) {
155 | // NSString -> NSURL
156 | // 字符串转码
157 | value = [value mj_url];
158 | } else if (type.isNumberType) {
159 | NSString *oldValue = value;
160 |
161 | // NSString -> NSNumber
162 | if (type.typeClass == [NSDecimalNumber class]) {
163 | value = [NSDecimalNumber decimalNumberWithString:oldValue];
164 | } else {
165 | value = [numberFormatter_ numberFromString:oldValue];
166 | }
167 |
168 | // 如果是BOOL
169 | if (type.isBoolType) {
170 | // 字符串转BOOL(字符串没有charValue方法)
171 | // 系统会调用字符串的charValue转为BOOL类型
172 | NSString *lower = [oldValue lowercaseString];
173 | if ([lower isEqualToString:@"yes"] || [lower isEqualToString:@"true"]) {
174 | value = @YES;
175 | } else if ([lower isEqualToString:@"no"] || [lower isEqualToString:@"false"]) {
176 | value = @NO;
177 | }
178 | }
179 | }
180 | }
181 |
182 | // value和property类型不匹配
183 | if (propertyClass && ![value isKindOfClass:propertyClass]) {
184 | value = nil;
185 | }
186 | }
187 |
188 | // 3.赋值
189 | [property setValue:value forObject:self];
190 | } @catch (NSException *exception) {
191 | MJExtensionBuildError([self class], exception.reason);
192 | MJExtensionLog(@"%@", exception);
193 | }
194 | }];
195 |
196 | // 转换完毕
197 | if ([self respondsToSelector:@selector(mj_keyValuesDidFinishConvertingToObject)]) {
198 | [self mj_keyValuesDidFinishConvertingToObject];
199 | }
200 | return self;
201 | }
202 |
203 | + (instancetype)mj_objectWithKeyValues:(id)keyValues
204 | {
205 | return [self mj_objectWithKeyValues:keyValues context:nil];
206 | }
207 |
208 | + (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
209 | {
210 | // 获得JSON对象
211 | keyValues = [keyValues mj_JSONObject];
212 | MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], nil, [self class], @"keyValues参数不是一个字典");
213 |
214 | if ([self isSubclassOfClass:[NSManagedObject class]] && context) {
215 | NSString *entityName = [NSStringFromClass(self) componentsSeparatedByString:@"."].lastObject;
216 | return [[NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context] mj_setKeyValues:keyValues context:context];
217 | }
218 | return [[[self alloc] init] mj_setKeyValues:keyValues];
219 | }
220 |
221 | + (instancetype)mj_objectWithFilename:(NSString *)filename
222 | {
223 | MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil");
224 |
225 | return [self mj_objectWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]];
226 | }
227 |
228 | + (instancetype)mj_objectWithFile:(NSString *)file
229 | {
230 | MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil");
231 |
232 | return [self mj_objectWithKeyValues:[NSDictionary dictionaryWithContentsOfFile:file]];
233 | }
234 |
235 | #pragma mark - 字典数组 -> 模型数组
236 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray
237 | {
238 | return [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:nil];
239 | }
240 |
241 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context
242 | {
243 | // 如果是JSON字符串
244 | keyValuesArray = [keyValuesArray mj_JSONObject];
245 |
246 | // 1.判断真实性
247 | MJExtensionAssertError([keyValuesArray isKindOfClass:[NSArray class]], nil, [self class], @"keyValuesArray参数不是一个数组");
248 |
249 | // 如果数组里面放的是NSString、NSNumber等数据
250 | if ([MJFoundation isClassFromFoundation:self]) return [NSMutableArray arrayWithArray:keyValuesArray];
251 |
252 |
253 | // 2.创建数组
254 | NSMutableArray *modelArray = [NSMutableArray array];
255 |
256 | // 3.遍历
257 | for (NSDictionary *keyValues in keyValuesArray) {
258 | if ([keyValues isKindOfClass:[NSArray class]]){
259 | [modelArray addObject:[self mj_objectArrayWithKeyValuesArray:keyValues context:context]];
260 | } else {
261 | id model = [self mj_objectWithKeyValues:keyValues context:context];
262 | if (model) [modelArray addObject:model];
263 | }
264 | }
265 |
266 | return modelArray;
267 | }
268 |
269 | + (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename
270 | {
271 | MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil");
272 |
273 | return [self mj_objectArrayWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]];
274 | }
275 |
276 | + (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file
277 | {
278 | MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil");
279 |
280 | return [self mj_objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:file]];
281 | }
282 |
283 | #pragma mark - 模型 -> 字典
284 | - (NSMutableDictionary *)mj_keyValues
285 | {
286 | return [self mj_keyValuesWithKeys:nil ignoredKeys:nil];
287 | }
288 |
289 | - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys
290 | {
291 | return [self mj_keyValuesWithKeys:keys ignoredKeys:nil];
292 | }
293 |
294 | - (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys
295 | {
296 | return [self mj_keyValuesWithKeys:nil ignoredKeys:ignoredKeys];
297 | }
298 |
299 | - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys
300 | {
301 | // 如果自己不是模型类, 那就返回自己
302 | MJExtensionAssertError(![MJFoundation isClassFromFoundation:[self class]], (NSMutableDictionary *)self, [self class], @"不是自定义的模型类")
303 |
304 | id keyValues = [NSMutableDictionary dictionary];
305 |
306 | Class clazz = [self class];
307 | NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames];
308 | NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames];
309 |
310 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
311 | @try {
312 | // 0.检测是否被忽略
313 | if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
314 | if ([ignoredPropertyNames containsObject:property.name]) return;
315 | if (keys.count && ![keys containsObject:property.name]) return;
316 | if ([ignoredKeys containsObject:property.name]) return;
317 |
318 | // 1.取出属性值
319 | id value = [property valueForObject:self];
320 | if (!value) return;
321 |
322 | // 2.如果是模型属性
323 | MJPropertyType *type = property.type;
324 | Class propertyClass = type.typeClass;
325 | if (!type.isFromFoundation && propertyClass) {
326 | value = [value mj_keyValues];
327 | } else if ([value isKindOfClass:[NSArray class]]) {
328 | // 3.处理数组里面有模型的情况
329 | value = [NSObject mj_keyValuesArrayWithObjectArray:value];
330 | } else if (propertyClass == [NSURL class]) {
331 | value = [value absoluteString];
332 | }
333 |
334 | // 4.赋值
335 | if ([clazz mj_isReferenceReplacedKeyWhenCreatingKeyValues]) {
336 | NSArray *propertyKeys = [[property propertyKeysForClass:clazz] firstObject];
337 | NSUInteger keyCount = propertyKeys.count;
338 | // 创建字典
339 | __block id innerContainer = keyValues;
340 | [propertyKeys enumerateObjectsUsingBlock:^(MJPropertyKey *propertyKey, NSUInteger idx, BOOL *stop) {
341 | // 下一个属性
342 | MJPropertyKey *nextPropertyKey = nil;
343 | if (idx != keyCount - 1) {
344 | nextPropertyKey = propertyKeys[idx + 1];
345 | }
346 |
347 | if (nextPropertyKey) { // 不是最后一个key
348 | // 当前propertyKey对应的字典或者数组
349 | id tempInnerContainer = [propertyKey valueInObject:innerContainer];
350 | if (tempInnerContainer == nil || [tempInnerContainer isKindOfClass:[NSNull class]]) {
351 | if (nextPropertyKey.type == MJPropertyKeyTypeDictionary) {
352 | tempInnerContainer = [NSMutableDictionary dictionary];
353 | } else {
354 | tempInnerContainer = [NSMutableArray array];
355 | }
356 | if (propertyKey.type == MJPropertyKeyTypeDictionary) {
357 | innerContainer[propertyKey.name] = tempInnerContainer;
358 | } else {
359 | innerContainer[propertyKey.name.intValue] = tempInnerContainer;
360 | }
361 | }
362 |
363 | if ([tempInnerContainer isKindOfClass:[NSMutableArray class]]) {
364 | NSMutableArray *tempInnerContainerArray = tempInnerContainer;
365 | int index = nextPropertyKey.name.intValue;
366 | while (tempInnerContainerArray.count < index + 1) {
367 | [tempInnerContainerArray addObject:[NSNull null]];
368 | }
369 | }
370 |
371 | innerContainer = tempInnerContainer;
372 | } else { // 最后一个key
373 | if (propertyKey.type == MJPropertyKeyTypeDictionary) {
374 | innerContainer[propertyKey.name] = value;
375 | } else {
376 | innerContainer[propertyKey.name.intValue] = value;
377 | }
378 | }
379 | }];
380 | } else {
381 | keyValues[property.name] = value;
382 | }
383 | } @catch (NSException *exception) {
384 | MJExtensionBuildError([self class], exception.reason);
385 | MJExtensionLog(@"%@", exception);
386 | }
387 | }];
388 |
389 | // 转换完毕
390 | if ([self respondsToSelector:@selector(mj_objectDidFinishConvertingToKeyValues)]) {
391 | [self mj_objectDidFinishConvertingToKeyValues];
392 | }
393 |
394 | return keyValues;
395 | }
396 | #pragma mark - 模型数组 -> 字典数组
397 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray
398 | {
399 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:nil];
400 | }
401 |
402 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys
403 | {
404 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys ignoredKeys:nil];
405 | }
406 |
407 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys
408 | {
409 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:ignoredKeys];
410 | }
411 |
412 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys
413 | {
414 | // 0.判断真实性
415 | MJExtensionAssertError([objectArray isKindOfClass:[NSArray class]], nil, [self class], @"objectArray参数不是一个数组");
416 |
417 | // 1.创建数组
418 | NSMutableArray *keyValuesArray = [NSMutableArray array];
419 | for (id object in objectArray) {
420 | if (keys) {
421 | [keyValuesArray addObject:[object mj_keyValuesWithKeys:keys]];
422 | } else {
423 | [keyValuesArray addObject:[object mj_keyValuesWithIgnoredKeys:ignoredKeys]];
424 | }
425 | }
426 | return keyValuesArray;
427 | }
428 |
429 | #pragma mark - 转换为JSON
430 | - (NSData *)mj_JSONData
431 | {
432 | if ([self isKindOfClass:[NSString class]]) {
433 | return [((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding];
434 | } else if ([self isKindOfClass:[NSData class]]) {
435 | return (NSData *)self;
436 | }
437 |
438 | return [NSJSONSerialization dataWithJSONObject:[self mj_JSONObject] options:kNilOptions error:nil];
439 | }
440 |
441 | - (id)mj_JSONObject
442 | {
443 | if ([self isKindOfClass:[NSString class]]) {
444 | return [NSJSONSerialization JSONObjectWithData:[((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
445 | } else if ([self isKindOfClass:[NSData class]]) {
446 | return [NSJSONSerialization JSONObjectWithData:(NSData *)self options:kNilOptions error:nil];
447 | }
448 |
449 | return self.mj_keyValues;
450 | }
451 |
452 | - (NSString *)mj_JSONString
453 | {
454 | if ([self isKindOfClass:[NSString class]]) {
455 | return (NSString *)self;
456 | } else if ([self isKindOfClass:[NSData class]]) {
457 | return [[NSString alloc] initWithData:(NSData *)self encoding:NSUTF8StringEncoding];
458 | }
459 |
460 | return [[NSString alloc] initWithData:[self mj_JSONData] encoding:NSUTF8StringEncoding];
461 | }
462 | @end
463 |
464 | @implementation NSObject (MJKeyValueDeprecated_v_2_5_16)
465 | - (instancetype)setKeyValues:(id)keyValues
466 | {
467 | return [self mj_setKeyValues:keyValues];
468 | }
469 |
470 | - (instancetype)setKeyValues:(id)keyValues error:(NSError **)error
471 | {
472 | id value = [self mj_setKeyValues:keyValues];
473 | if (error != NULL) {
474 | *error = [self.class mj_error];
475 | }
476 | return value;
477 |
478 | }
479 |
480 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
481 | {
482 | return [self mj_setKeyValues:keyValues context:context];
483 | }
484 |
485 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error
486 | {
487 | id value = [self mj_setKeyValues:keyValues context:context];
488 | if (error != NULL) {
489 | *error = [self.class mj_error];
490 | }
491 | return value;
492 | }
493 |
494 | + (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference
495 | {
496 | [self mj_referenceReplacedKeyWhenCreatingKeyValues:reference];
497 | }
498 |
499 | - (NSMutableDictionary *)keyValues
500 | {
501 | return [self mj_keyValues];
502 | }
503 |
504 | - (NSMutableDictionary *)keyValuesWithError:(NSError **)error
505 | {
506 | id value = [self mj_keyValues];
507 | if (error != NULL) {
508 | *error = [self.class mj_error];
509 | }
510 | return value;
511 | }
512 |
513 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys
514 | {
515 | return [self mj_keyValuesWithKeys:keys];
516 | }
517 |
518 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error
519 | {
520 | id value = [self mj_keyValuesWithKeys:keys];
521 | if (error != NULL) {
522 | *error = [self.class mj_error];
523 | }
524 | return value;
525 | }
526 |
527 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys
528 | {
529 | return [self mj_keyValuesWithIgnoredKeys:ignoredKeys];
530 | }
531 |
532 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error
533 | {
534 | id value = [self mj_keyValuesWithIgnoredKeys:ignoredKeys];
535 | if (error != NULL) {
536 | *error = [self.class mj_error];
537 | }
538 | return value;
539 | }
540 |
541 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray
542 | {
543 | return [self mj_keyValuesArrayWithObjectArray:objectArray];
544 | }
545 |
546 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error
547 | {
548 | id value = [self mj_keyValuesArrayWithObjectArray:objectArray];
549 | if (error != NULL) {
550 | *error = [self mj_error];
551 | }
552 | return value;
553 | }
554 |
555 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys
556 | {
557 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys];
558 | }
559 |
560 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error
561 | {
562 | id value = [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys];
563 | if (error != NULL) {
564 | *error = [self mj_error];
565 | }
566 | return value;
567 | }
568 |
569 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys
570 | {
571 | return [self mj_keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys];
572 | }
573 |
574 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error
575 | {
576 | id value = [self mj_keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys];
577 | if (error != NULL) {
578 | *error = [self mj_error];
579 | }
580 | return value;
581 | }
582 |
583 | + (instancetype)objectWithKeyValues:(id)keyValues
584 | {
585 | return [self mj_objectWithKeyValues:keyValues];
586 | }
587 |
588 | + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error
589 | {
590 | id value = [self mj_objectWithKeyValues:keyValues];
591 | if (error != NULL) {
592 | *error = [self mj_error];
593 | }
594 | return value;
595 | }
596 |
597 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
598 | {
599 | return [self mj_objectWithKeyValues:keyValues context:context];
600 | }
601 |
602 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error
603 | {
604 | id value = [self mj_objectWithKeyValues:keyValues context:context];
605 | if (error != NULL) {
606 | *error = [self mj_error];
607 | }
608 | return value;
609 | }
610 |
611 | + (instancetype)objectWithFilename:(NSString *)filename
612 | {
613 | return [self mj_objectWithFilename:filename];
614 | }
615 |
616 | + (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error
617 | {
618 | id value = [self mj_objectWithFilename:filename];
619 | if (error != NULL) {
620 | *error = [self mj_error];
621 | }
622 | return value;
623 | }
624 |
625 | + (instancetype)objectWithFile:(NSString *)file
626 | {
627 | return [self mj_objectWithFile:file];
628 | }
629 |
630 | + (instancetype)objectWithFile:(NSString *)file error:(NSError **)error
631 | {
632 | id value = [self mj_objectWithFile:file];
633 | if (error != NULL) {
634 | *error = [self mj_error];
635 | }
636 | return value;
637 | }
638 |
639 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray
640 | {
641 | return [self mj_objectArrayWithKeyValuesArray:keyValuesArray];
642 | }
643 |
644 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error
645 | {
646 | id value = [self mj_objectArrayWithKeyValuesArray:keyValuesArray];
647 | if (error != NULL) {
648 | *error = [self mj_error];
649 | }
650 | return value;
651 | }
652 |
653 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context
654 | {
655 | return [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:context];
656 | }
657 |
658 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error
659 | {
660 | id value = [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:context];
661 | if (error != NULL) {
662 | *error = [self mj_error];
663 | }
664 | return value;
665 | }
666 |
667 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename
668 | {
669 | return [self mj_objectArrayWithFilename:filename];
670 | }
671 |
672 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error
673 | {
674 | id value = [self mj_objectArrayWithFilename:filename];
675 | if (error != NULL) {
676 | *error = [self mj_error];
677 | }
678 | return value;
679 | }
680 |
681 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file
682 | {
683 | return [self mj_objectArrayWithFile:file];
684 | }
685 |
686 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error
687 | {
688 | id value = [self mj_objectArrayWithFile:file];
689 | if (error != NULL) {
690 | *error = [self mj_error];
691 | }
692 | return value;
693 | }
694 |
695 | - (NSData *)JSONData
696 | {
697 | return [self mj_JSONData];
698 | }
699 |
700 | - (id)JSONObject
701 | {
702 | return [self mj_JSONObject];
703 | }
704 |
705 | - (NSString *)JSONString
706 | {
707 | return [self mj_JSONString];
708 | }
709 | @end
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJProperty.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJProperty.h
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/4/17.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MJExtensionConst.h"
11 |
12 | @class MJProperty;
13 |
14 | /**
15 | * 遍历成员变量用的block
16 | *
17 | * @param property 成员的包装对象
18 | * @param stop YES代表停止遍历,NO代表继续遍历
19 | */
20 | typedef void (^MJPropertiesEnumeration)(MJProperty *property, BOOL *stop);
21 |
22 | /** 将属性名换为其他key去字典中取值 */
23 | typedef NSDictionary * (^MJReplacedKeyFromPropertyName)();
24 | typedef id (^MJReplacedKeyFromPropertyName121)(NSString *propertyName);
25 | /** 数组中需要转换的模型类 */
26 | typedef NSDictionary * (^MJObjectClassInArray)();
27 | /** 用于过滤字典中的值 */
28 | typedef id (^MJNewValueFromOldValue)(id object, id oldValue, MJProperty *property);
29 |
30 | /**
31 | * 成员属性相关的扩展
32 | */
33 | @interface NSObject (MJProperty)
34 | #pragma mark - 遍历
35 | /**
36 | * 遍历所有的成员
37 | */
38 | + (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration;
39 |
40 | #pragma mark - 新值配置
41 | /**
42 | * 用于过滤字典中的值
43 | *
44 | * @param newValueFormOldValue 用于过滤字典中的值
45 | */
46 | + (void)mj_setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue;
47 | + (id)mj_getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property;
48 |
49 | #pragma mark - key配置
50 | /**
51 | * 将属性名换为其他key去字典中取值
52 | *
53 | * @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值
54 | */
55 | + (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName;
56 | /**
57 | * 将属性名换为其他key去字典中取值
58 | *
59 | * @param replacedKeyFromPropertyName121 将属性名换为其他key去字典中取值
60 | */
61 | + (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121;
62 |
63 | #pragma mark - array model class配置
64 | /**
65 | * 数组中需要转换的模型类
66 | *
67 | * @param objectClassInArray 数组中需要转换的模型类
68 | */
69 | + (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray;
70 | @end
71 |
72 | @interface NSObject (MJPropertyDeprecated_v_2_5_16)
73 | + (void)enumerateProperties:(MJPropertiesEnumeration)enumeration MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
74 | + (void)setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
75 | + (id)getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
76 | + (void)setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
77 | + (void)setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121 MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
78 | + (void)setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
79 | @end
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSObject+MJProperty.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+MJProperty.m
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/4/17.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "NSObject+MJProperty.h"
10 | #import "NSObject+MJKeyValue.h"
11 | #import "NSObject+MJCoding.h"
12 | #import "NSObject+MJClass.h"
13 | #import "MJProperty.h"
14 | #import "MJFoundation.h"
15 | #import
16 |
17 | #pragma clang diagnostic push
18 | #pragma clang diagnostic ignored "-Wundeclared-selector"
19 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
20 |
21 | static const char MJReplacedKeyFromPropertyNameKey = '\0';
22 | static const char MJReplacedKeyFromPropertyName121Key = '\0';
23 | static const char MJNewValueFromOldValueKey = '\0';
24 | static const char MJObjectClassInArrayKey = '\0';
25 |
26 | static const char MJCachedPropertiesKey = '\0';
27 |
28 | @implementation NSObject (Property)
29 |
30 | static NSMutableDictionary *replacedKeyFromPropertyNameDict_;
31 | static NSMutableDictionary *replacedKeyFromPropertyName121Dict_;
32 | static NSMutableDictionary *newValueFromOldValueDict_;
33 | static NSMutableDictionary *objectClassInArrayDict_;
34 | static NSMutableDictionary *cachedPropertiesDict_;
35 |
36 | + (void)load
37 | {
38 | replacedKeyFromPropertyNameDict_ = [NSMutableDictionary dictionary];
39 | replacedKeyFromPropertyName121Dict_ = [NSMutableDictionary dictionary];
40 | newValueFromOldValueDict_ = [NSMutableDictionary dictionary];
41 | objectClassInArrayDict_ = [NSMutableDictionary dictionary];
42 | cachedPropertiesDict_ = [NSMutableDictionary dictionary];
43 | }
44 |
45 | + (NSMutableDictionary *)dictForKey:(const void *)key
46 | {
47 | @synchronized (self) {
48 | if (key == &MJReplacedKeyFromPropertyNameKey) return replacedKeyFromPropertyNameDict_;
49 | if (key == &MJReplacedKeyFromPropertyName121Key) return replacedKeyFromPropertyName121Dict_;
50 | if (key == &MJNewValueFromOldValueKey) return newValueFromOldValueDict_;
51 | if (key == &MJObjectClassInArrayKey) return objectClassInArrayDict_;
52 | if (key == &MJCachedPropertiesKey) return cachedPropertiesDict_;
53 | return nil;
54 | }
55 | }
56 |
57 | #pragma mark - --私有方法--
58 | + (id)propertyKey:(NSString *)propertyName
59 | {
60 | MJExtensionAssertParamNotNil2(propertyName, nil);
61 |
62 | __block id key = nil;
63 | // 查看有没有需要替换的key
64 | if ([self respondsToSelector:@selector(mj_replacedKeyFromPropertyName121:)]) {
65 | key = [self mj_replacedKeyFromPropertyName121:propertyName];
66 | }
67 | // 兼容旧版本
68 | if ([self respondsToSelector:@selector(replacedKeyFromPropertyName121:)]) {
69 | key = [self performSelector:@selector(replacedKeyFromPropertyName121) withObject:propertyName];
70 | }
71 |
72 | // 调用block
73 | if (!key) {
74 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
75 | MJReplacedKeyFromPropertyName121 block = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyName121Key);
76 | if (block) {
77 | key = block(propertyName);
78 | }
79 | if (key) *stop = YES;
80 | }];
81 | }
82 |
83 | // 查看有没有需要替换的key
84 | if ((!key || [key isEqual:propertyName]) && [self respondsToSelector:@selector(mj_replacedKeyFromPropertyName)]) {
85 | key = [self mj_replacedKeyFromPropertyName][propertyName];
86 | }
87 | // 兼容旧版本
88 | if ((!key || [key isEqual:propertyName]) && [self respondsToSelector:@selector(replacedKeyFromPropertyName)]) {
89 | key = [self performSelector:@selector(replacedKeyFromPropertyName)][propertyName];
90 | }
91 |
92 | if (!key || [key isEqual:propertyName]) {
93 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
94 | NSDictionary *dict = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyNameKey);
95 | if (dict) {
96 | key = dict[propertyName];
97 | }
98 | if (key && ![key isEqual:propertyName]) *stop = YES;
99 | }];
100 | }
101 |
102 | // 2.用属性名作为key
103 | if (!key) key = propertyName;
104 |
105 | return key;
106 | }
107 |
108 | + (Class)propertyObjectClassInArray:(NSString *)propertyName
109 | {
110 | __block id clazz = nil;
111 | if ([self respondsToSelector:@selector(mj_objectClassInArray)]) {
112 | clazz = [self mj_objectClassInArray][propertyName];
113 | }
114 | // 兼容旧版本
115 | if ([self respondsToSelector:@selector(objectClassInArray)]) {
116 | clazz = [self performSelector:@selector(objectClassInArray)][propertyName];
117 | }
118 |
119 | if (!clazz) {
120 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
121 | NSDictionary *dict = objc_getAssociatedObject(c, &MJObjectClassInArrayKey);
122 | if (dict) {
123 | clazz = dict[propertyName];
124 | }
125 | if (clazz) *stop = YES;
126 | }];
127 | }
128 |
129 | // 如果是NSString类型
130 | if ([clazz isKindOfClass:[NSString class]]) {
131 | clazz = NSClassFromString(clazz);
132 | }
133 | return clazz;
134 | }
135 |
136 | #pragma mark - --公共方法--
137 | + (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration
138 | {
139 | // 获得成员变量
140 | NSArray *cachedProperties = [self properties];
141 |
142 | // 遍历成员变量
143 | BOOL stop = NO;
144 | for (MJProperty *property in cachedProperties) {
145 | enumeration(property, &stop);
146 | if (stop) break;
147 | }
148 | }
149 |
150 | #pragma mark - 公共方法
151 | + (NSMutableArray *)properties
152 | {
153 | NSMutableArray *cachedProperties = [self dictForKey:&MJCachedPropertiesKey][NSStringFromClass(self)];
154 |
155 | if (cachedProperties == nil) {
156 | cachedProperties = [NSMutableArray array];
157 |
158 | [self mj_enumerateClasses:^(__unsafe_unretained Class c, BOOL *stop) {
159 | // 1.获得所有的成员变量
160 | unsigned int outCount = 0;
161 | objc_property_t *properties = class_copyPropertyList(c, &outCount);
162 |
163 | // 2.遍历每一个成员变量
164 | for (unsigned int i = 0; i
10 | #import "MJExtensionConst.h"
11 |
12 | @interface NSString (MJExtension)
13 | /**
14 | * 驼峰转下划线(loveYou -> love_you)
15 | */
16 | - (NSString *)mj_underlineFromCamel;
17 | /**
18 | * 下划线转驼峰(love_you -> loveYou)
19 | */
20 | - (NSString *)mj_camelFromUnderline;
21 | /**
22 | * 首字母变大写
23 | */
24 | - (NSString *)mj_firstCharUpper;
25 | /**
26 | * 首字母变小写
27 | */
28 | - (NSString *)mj_firstCharLower;
29 |
30 | - (BOOL)mj_isPureInt;
31 |
32 | - (NSURL *)mj_url;
33 | @end
34 |
35 | @interface NSString (MJExtensionDeprecated_v_2_5_16)
36 | - (NSString *)underlineFromCamel MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
37 | - (NSString *)camelFromUnderline MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
38 | - (NSString *)firstCharUpper MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
39 | - (NSString *)firstCharLower MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
40 | - (BOOL)isPureInt MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
41 | - (NSURL *)url MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***");
42 | @end
43 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/MJExtension/NSString+MJExtension.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+MJExtension.m
3 | // MJExtensionExample
4 | //
5 | // Created by MJ Lee on 15/6/7.
6 | // Copyright (c) 2015年 小码哥. All rights reserved.
7 | //
8 |
9 | #import "NSString+MJExtension.h"
10 |
11 | @implementation NSString (MJExtension)
12 | - (NSString *)mj_underlineFromCamel
13 | {
14 | if (self.length == 0) return self;
15 | NSMutableString *string = [NSMutableString string];
16 | for (NSUInteger i = 0; i= 2) [string appendString:[cmp substringFromIndex:1]];
40 | } else {
41 | [string appendString:cmp];
42 | }
43 | }
44 | return string;
45 | }
46 |
47 | - (NSString *)mj_firstCharLower
48 | {
49 | if (self.length == 0) return self;
50 | NSMutableString *string = [NSMutableString string];
51 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].lowercaseString];
52 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]];
53 | return string;
54 | }
55 |
56 | - (NSString *)mj_firstCharUpper
57 | {
58 | if (self.length == 0) return self;
59 | NSMutableString *string = [NSMutableString string];
60 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].uppercaseString];
61 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]];
62 | return string;
63 | }
64 |
65 | - (BOOL)mj_isPureInt
66 | {
67 | NSScanner *scan = [NSScanner scannerWithString:self];
68 | int val;
69 | return [scan scanInt:&val] && [scan isAtEnd];
70 | }
71 |
72 | - (NSURL *)mj_url
73 | {
74 | // [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"!$&'()*+,-./:;=?@_~%#[]"]];
75 | #pragma clang diagnostic push
76 | #pragma clang diagnostic ignored"-Wdeprecated-declarations"
77 | return [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))];
78 | #pragma clang diagnostic pop
79 | }
80 | @end
81 |
82 | @implementation NSString (MJExtensionDeprecated_v_2_5_16)
83 | - (NSString *)underlineFromCamel
84 | {
85 | return self.mj_underlineFromCamel;
86 | }
87 |
88 | - (NSString *)camelFromUnderline
89 | {
90 | return self.mj_camelFromUnderline;
91 | }
92 |
93 | - (NSString *)firstCharLower
94 | {
95 | return self.mj_firstCharLower;
96 | }
97 |
98 | - (NSString *)firstCharUpper
99 | {
100 | return self.mj_firstCharUpper;
101 | }
102 |
103 | - (BOOL)isPureInt
104 | {
105 | return self.mj_isPureInt;
106 | }
107 |
108 | - (NSURL *)url
109 | {
110 | return self.mj_url;
111 | }
112 | @end
113 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/MJExtension/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 | MJExtension
4 | ===
5 | - A fast, convenient and nonintrusive conversion between JSON and model.
6 | - 转换速度快、使用简单方便的字典转模型框架
7 |
8 | GitHub:[CoderMJLee](https://github.com/CoderMJLee) | Blog:[mjios(Chinese)](http://www.cnblogs.com/mjios) | PR is welcome,or [feedback](mailto:richermj123go@vip.qq.com)
9 |
10 |
11 | ## Contents
12 | * [Getting Started 【开始使用】](#Getting_Started)
13 | * [Features 【能做什么】](#Features)
14 | * [Installation 【安装】](#Installation)
15 | * [Examples 【示例】](#Examples)
16 | * [JSON -> Model](#JSON_Model)
17 | * [JSONString -> Model](#JSONString_Model)
18 | * [Model contains model](#Model_contains_model)
19 | * [Model contains model-array](#Model_contains_model_array)
20 | * [Model name - JSON key mapping](#Model_name_JSON_key_mapping)
21 | * [JSON array -> model array](#JSON_array_model_array)
22 | * [Model -> JSON](#Model_JSON)
23 | * [Model array -> JSON array](#Model_array_JSON_array)
24 | * [Core Data](#Core_Data)
25 | * [Coding](#Coding)
26 | * [Camel -> underline](#Camel_underline)
27 | * [NSString -> NSDate, nil -> @""](#NSString_NSDate)
28 | * [More use cases](#More_use_cases)
29 |
30 | ---
31 |
32 | # Getting Started【开始使用】
33 |
34 | ## Features【能做什么】
35 | - MJExtension是一套字典和模型之间互相转换的超轻量级框架
36 | * `JSON` --> `Model`、`Core Data Model`
37 | * `JSONString` --> `Model`、`Core Data Model`
38 | * `Model`、`Core Data Model` --> `JSON`
39 | * `JSON Array` --> `Model Array`、`Core Data Model Array`
40 | * `JSONString` --> `Model Array`、`Core Data Model Array`
41 | * `Model Array`、`Core Data Model Array` --> `JSON Array`
42 | * Coding all properties of model in one line code.
43 | * 只需要一行代码,就能实现模型的所有属性进行Coding(归档和解档)
44 |
45 | ## Installation【安装】
46 |
47 | ### From CocoaPods【使用CocoaPods】
48 |
49 | ```ruby
50 | pod 'MJExtension'
51 | ```
52 |
53 | ### Manually【手动导入】
54 | - Drag all source files under floder `MJExtension` to your project.【将`MJExtension`文件夹中的所有源代码拽入项目中】
55 | - Import the main header file:`#import "MJExtension.h"`【导入主头文件:`#import "MJExtension.h"`】
56 |
57 | ```objc
58 | MJExtension.h
59 | MJConst.h MJConst.m
60 | MJFoundation.h MJFoundation.m
61 | MJProperty.h MJProperty.m
62 | MJType.h MJType.m
63 | NSObject+MJCoding.h NSObject+MJCoding.m
64 | NSObject+MJProperty.h NSObject+MJProperty.m
65 | NSObject+MJKeyValue.h NSObject+MJKeyValue.m
66 | ```
67 |
68 | # Examples【示例】
69 |
70 | ### The most simple JSON -> Model【最简单的字典转模型】
71 |
72 | ```objc
73 | typedef enum {
74 | SexMale,
75 | SexFemale
76 | } Sex;
77 |
78 | @interface User : NSObject
79 | @property (copy, nonatomic) NSString *name;
80 | @property (copy, nonatomic) NSString *icon;
81 | @property (assign, nonatomic) unsigned int age;
82 | @property (copy, nonatomic) NSString *height;
83 | @property (strong, nonatomic) NSNumber *money;
84 | @property (assign, nonatomic) Sex sex;
85 | @property (assign, nonatomic, getter=isGay) BOOL gay;
86 | @end
87 |
88 | /***********************************************/
89 |
90 | NSDictionary *dict = @{
91 | @"name" : @"Jack",
92 | @"icon" : @"lufy.png",
93 | @"age" : @20,
94 | @"height" : @"1.55",
95 | @"money" : @100.9,
96 | @"sex" : @(SexFemale),
97 | @"gay" : @"true"
98 | // @"gay" : @"1"
99 | // @"gay" : @"NO"
100 | };
101 |
102 | // JSON -> User
103 | User *user = [User mj_objectWithKeyValues:dict];
104 |
105 | NSLog(@"name=%@, icon=%@, age=%zd, height=%@, money=%@, sex=%d, gay=%d", user.name, user.icon, user.age, user.height, user.money, user.sex, user.gay);
106 | // name=Jack, icon=lufy.png, age=20, height=1.550000, money=100.9, sex=1
107 | ```
108 |
109 | ### JSONString -> Model【JSON字符串转模型】
110 |
111 | ```objc
112 | // 1.Define a JSONString
113 | NSString *jsonString = @"{\"name\":\"Jack\", \"icon\":\"lufy.png\", \"age\":20}";
114 |
115 | // 2.JSONString -> User
116 | User *user = [User mj_objectWithKeyValues:jsonString];
117 |
118 | // 3.Print user's properties
119 | NSLog(@"name=%@, icon=%@, age=%d", user.name, user.icon, user.age);
120 | // name=Jack, icon=lufy.png, age=20
121 | ```
122 |
123 | ### Model contains model【模型中嵌套模型】
124 |
125 | ```objc
126 | @interface Status : NSObject
127 | @property (copy, nonatomic) NSString *text;
128 | @property (strong, nonatomic) User *user;
129 | @property (strong, nonatomic) Status *retweetedStatus;
130 | @end
131 |
132 | /***********************************************/
133 |
134 | NSDictionary *dict = @{
135 | @"text" : @"Agree!Nice weather!",
136 | @"user" : @{
137 | @"name" : @"Jack",
138 | @"icon" : @"lufy.png"
139 | },
140 | @"retweetedStatus" : @{
141 | @"text" : @"Nice weather!",
142 | @"user" : @{
143 | @"name" : @"Rose",
144 | @"icon" : @"nami.png"
145 | }
146 | }
147 | };
148 |
149 | // JSON -> Status
150 | Status *status = [Status mj_objectWithKeyValues:dict];
151 |
152 | NSString *text = status.text;
153 | NSString *name = status.user.name;
154 | NSString *icon = status.user.icon;
155 | NSLog(@"text=%@, name=%@, icon=%@", text, name, icon);
156 | // text=Agree!Nice weather!, name=Jack, icon=lufy.png
157 |
158 | NSString *text2 = status.retweetedStatus.text;
159 | NSString *name2 = status.retweetedStatus.user.name;
160 | NSString *icon2 = status.retweetedStatus.user.icon;
161 | NSLog(@"text2=%@, name2=%@, icon2=%@", text2, name2, icon2);
162 | // text2=Nice weather!, name2=Rose, icon2=nami.png
163 | ```
164 |
165 | ### Model contains model-array【模型中有个数组属性,数组里面又要装着其他模型】
166 |
167 | ```objc
168 | @interface Ad : NSObject
169 | @property (copy, nonatomic) NSString *image;
170 | @property (copy, nonatomic) NSString *url;
171 | @end
172 |
173 | @interface StatusResult : NSObject
174 | /** Contatins status model */
175 | @property (strong, nonatomic) NSMutableArray *statuses;
176 | /** Contatins ad model */
177 | @property (strong, nonatomic) NSArray *ads;
178 | @property (strong, nonatomic) NSNumber *totalNumber;
179 | @end
180 |
181 | /***********************************************/
182 |
183 | // Tell MJExtension what type model will be contained in statuses and ads.
184 | [StatusResult mj_setupObjectClassInArray:^NSDictionary *{
185 | return @{
186 | @"statuses" : @"Status",
187 | // @"statuses" : [Status class],
188 | @"ads" : @"Ad"
189 | // @"ads" : [Ad class]
190 | };
191 | }];
192 | // Equals: StatusResult.m implements +mj_objectClassInArray method.
193 |
194 | NSDictionary *dict = @{
195 | @"statuses" : @[
196 | @{
197 | @"text" : @"Nice weather!",
198 | @"user" : @{
199 | @"name" : @"Rose",
200 | @"icon" : @"nami.png"
201 | }
202 | },
203 | @{
204 | @"text" : @"Go camping tomorrow!",
205 | @"user" : @{
206 | @"name" : @"Jack",
207 | @"icon" : @"lufy.png"
208 | }
209 | }
210 | ],
211 | @"ads" : @[
212 | @{
213 | @"image" : @"ad01.png",
214 | @"url" : @"http://www.ad01.com"
215 | },
216 | @{
217 | @"image" : @"ad02.png",
218 | @"url" : @"http://www.ad02.com"
219 | }
220 | ],
221 | @"totalNumber" : @"2014"
222 | };
223 |
224 | // JSON -> StatusResult
225 | StatusResult *result = [StatusResult mj_objectWithKeyValues:dict];
226 |
227 | NSLog(@"totalNumber=%@", result.totalNumber);
228 | // totalNumber=2014
229 |
230 | // Printing
231 | for (Status *status in result.statuses) {
232 | NSString *text = status.text;
233 | NSString *name = status.user.name;
234 | NSString *icon = status.user.icon;
235 | NSLog(@"text=%@, name=%@, icon=%@", text, name, icon);
236 | }
237 | // text=Nice weather!, name=Rose, icon=nami.png
238 | // text=Go camping tomorrow!, name=Jack, icon=lufy.png
239 |
240 | // Printing
241 | for (Ad *ad in result.ads) {
242 | NSLog(@"image=%@, url=%@", ad.image, ad.url);
243 | }
244 | // image=ad01.png, url=http://www.ad01.com
245 | // image=ad02.png, url=http://www.ad02.com
246 | ```
247 |
248 | ### Model name - JSON key mapping【模型中的属性名和字典中的key不相同(或者需要多级映射)】
249 |
250 | ```objc
251 | @interface Bag : NSObject
252 | @property (copy, nonatomic) NSString *name;
253 | @property (assign, nonatomic) double price;
254 | @end
255 |
256 | @interface Student : NSObject
257 | @property (copy, nonatomic) NSString *ID;
258 | @property (copy, nonatomic) NSString *desc;
259 | @property (copy, nonatomic) NSString *nowName;
260 | @property (copy, nonatomic) NSString *oldName;
261 | @property (copy, nonatomic) NSString *nameChangedTime;
262 | @property (strong, nonatomic) Bag *bag;
263 | @end
264 |
265 | /***********************************************/
266 |
267 | // How to map
268 | [Student mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
269 | return @{
270 | @"ID" : @"id",
271 | @"desc" : @"desciption",
272 | @"oldName" : @"name.oldName",
273 | @"nowName" : @"name.newName",
274 | @"nameChangedTime" : @"name.info[1].nameChangedTime",
275 | @"bag" : @"other.bag"
276 | };
277 | }];
278 | // Equals: Student.m implements +mj_replacedKeyFromPropertyName method.
279 |
280 | NSDictionary *dict = @{
281 | @"id" : @"20",
282 | @"desciption" : @"kids",
283 | @"name" : @{
284 | @"newName" : @"lufy",
285 | @"oldName" : @"kitty",
286 | @"info" : @[
287 | @"test-data",
288 | @{
289 | @"nameChangedTime" : @"2013-08"
290 | }
291 | ]
292 | },
293 | @"other" : @{
294 | @"bag" : @{
295 | @"name" : @"a red bag",
296 | @"price" : @100.7
297 | }
298 | }
299 | };
300 |
301 | // JSON -> Student
302 | Student *stu = [Student mj_objectWithKeyValues:dict];
303 |
304 | // Printing
305 | NSLog(@"ID=%@, desc=%@, oldName=%@, nowName=%@, nameChangedTime=%@",
306 | stu.ID, stu.desc, stu.oldName, stu.nowName, stu.nameChangedTime);
307 | // ID=20, desc=kids, oldName=kitty, nowName=lufy, nameChangedTime=2013-08
308 | NSLog(@"bagName=%@, bagPrice=%f", stu.bag.name, stu.bag.price);
309 | // bagName=a red bag, bagPrice=100.700000
310 | ```
311 |
312 |
313 | ### JSON array -> model array【将一个字典数组转成模型数组】
314 |
315 | ```objc
316 | NSArray *dictArray = @[
317 | @{
318 | @"name" : @"Jack",
319 | @"icon" : @"lufy.png"
320 | },
321 | @{
322 | @"name" : @"Rose",
323 | @"icon" : @"nami.png"
324 | }
325 | ];
326 |
327 | // JSON array -> User array
328 | NSArray *userArray = [User mj_objectArrayWithKeyValuesArray:dictArray];
329 |
330 | // Printing
331 | for (User *user in userArray) {
332 | NSLog(@"name=%@, icon=%@", user.name, user.icon);
333 | }
334 | // name=Jack, icon=lufy.png
335 | // name=Rose, icon=nami.png
336 | ```
337 |
338 | ### Model -> JSON【将一个模型转成字典】
339 | ```objc
340 | // New model
341 | User *user = [[User alloc] init];
342 | user.name = @"Jack";
343 | user.icon = @"lufy.png";
344 |
345 | Status *status = [[Status alloc] init];
346 | status.user = user;
347 | status.text = @"Nice mood!";
348 |
349 | // Status -> JSON
350 | NSDictionary *statusDict = status.mj_keyValues;
351 | NSLog(@"%@", statusDict);
352 | /*
353 | {
354 | text = "Nice mood!";
355 | user = {
356 | icon = "lufy.png";
357 | name = Jack;
358 | };
359 | }
360 | */
361 |
362 | // More complex situation
363 | Student *stu = [[Student alloc] init];
364 | stu.ID = @"123";
365 | stu.oldName = @"rose";
366 | stu.nowName = @"jack";
367 | stu.desc = @"handsome";
368 | stu.nameChangedTime = @"2018-09-08";
369 |
370 | Bag *bag = [[Bag alloc] init];
371 | bag.name = @"a red bag";
372 | bag.price = 205;
373 | stu.bag = bag;
374 |
375 | NSDictionary *stuDict = stu.mj_keyValues;
376 | NSLog(@"%@", stuDict);
377 | /*
378 | {
379 | ID = 123;
380 | bag = {
381 | name = "\U5c0f\U4e66\U5305";
382 | price = 205;
383 | };
384 | desc = handsome;
385 | nameChangedTime = "2018-09-08";
386 | nowName = jack;
387 | oldName = rose;
388 | }
389 | */
390 | ```
391 |
392 | ### Model array -> JSON array【将一个模型数组转成字典数组】
393 |
394 | ```objc
395 | // New model array
396 | User *user1 = [[User alloc] init];
397 | user1.name = @"Jack";
398 | user1.icon = @"lufy.png";
399 |
400 | User *user2 = [[User alloc] init];
401 | user2.name = @"Rose";
402 | user2.icon = @"nami.png";
403 |
404 | NSArray *userArray = @[user1, user2];
405 |
406 | // Model array -> JSON array
407 | NSArray *dictArray = [User mj_keyValuesArrayWithObjectArray:userArray];
408 | NSLog(@"%@", dictArray);
409 | /*
410 | (
411 | {
412 | icon = "lufy.png";
413 | name = Jack;
414 | },
415 | {
416 | icon = "nami.png";
417 | name = Rose;
418 | }
419 | )
420 | */
421 | ```
422 |
423 | ### Core Data
424 |
425 | ```objc
426 | NSDictionary *dict = @{
427 | @"name" : @"Jack",
428 | @"icon" : @"lufy.png",
429 | @"age" : @20,
430 | @"height" : @1.55,
431 | @"money" : @"100.9",
432 | @"sex" : @(SexFemale),
433 | @"gay" : @"true"
434 | };
435 |
436 | // This demo just provide simple steps
437 | NSManagedObjectContext *context = nil;
438 | User *user = [User mj_objectWithKeyValues:dict context:context];
439 |
440 | [context save:nil];
441 | ```
442 |
443 | ### Coding
444 |
445 | ```objc
446 | #import "MJExtension.h"
447 |
448 | @implementation Bag
449 | // NSCoding Implementation
450 | MJExtensionCodingImplementation
451 | @end
452 |
453 | /***********************************************/
454 |
455 | // what properties not to be coded
456 | [Bag mj_setupIgnoredCodingPropertyNames:^NSArray *{
457 | return @[@"name"];
458 | }];
459 | // Equals: Bag.m implements +mj_ignoredCodingPropertyNames method.
460 |
461 | // Create model
462 | Bag *bag = [[Bag alloc] init];
463 | bag.name = @"Red bag";
464 | bag.price = 200.8;
465 |
466 | NSString *file = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/bag.data"];
467 | // Encoding
468 | [NSKeyedArchiver archiveRootObject:bag toFile:file];
469 |
470 | // Decoding
471 | Bag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
472 | NSLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);
473 | // name=(null), price=200.800000
474 | ```
475 |
476 | ### Camel -> underline【统一转换属性名(比如驼峰转下划线)】
477 | ```objc
478 | // Dog
479 | #import "MJExtension.h"
480 |
481 | @implementation Dog
482 | + (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName
483 | {
484 | // nickName -> nick_name
485 | return [propertyName mj_underlineFromCamel];
486 | }
487 | @end
488 |
489 | // NSDictionary
490 | NSDictionary *dict = @{
491 | @"nick_name" : @"旺财",
492 | @"sale_price" : @"10.5",
493 | @"run_speed" : @"100.9"
494 | };
495 | // NSDictionary -> Dog
496 | Dog *dog = [Dog mj_objectWithKeyValues:dict];
497 |
498 | // printing
499 | NSLog(@"nickName=%@, scalePrice=%f runSpeed=%f", dog.nickName, dog.salePrice, dog.runSpeed);
500 | ```
501 |
502 | ### NSString -> NSDate, nil -> @""【过滤字典的值(比如字符串日期处理为NSDate、字符串nil处理为@"")】
503 | ```objc
504 | // Book
505 | #import "MJExtension.h"
506 |
507 | @implementation Book
508 | - (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property
509 | {
510 | if ([property.name isEqualToString:@"publisher"]) {
511 | if (oldValue == nil) return @"";
512 | } else if (property.type.typeClass == [NSDate class]) {
513 | NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
514 | fmt.dateFormat = @"yyyy-MM-dd";
515 | return [fmt dateFromString:oldValue];
516 | }
517 |
518 | return oldValue;
519 | }
520 | @end
521 |
522 | // NSDictionary
523 | NSDictionary *dict = @{
524 | @"name" : @"5分钟突破iOS开发",
525 | @"publishedTime" : @"2011-09-10"
526 | };
527 | // NSDictionary -> Book
528 | Book *book = [Book mj_objectWithKeyValues:dict];
529 |
530 | // printing
531 | NSLog(@"name=%@, publisher=%@, publishedTime=%@", book.name, book.publisher, book.publishedTime);
532 | ```
533 |
534 | ### More use cases【更多用法】
535 | - Please reference to `NSObject+MJKeyValue.h` and `NSObject+MJCoding.h`
536 |
537 |
538 | ## 期待
539 | * 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的框架代码看看BUG修复没有)
540 | * 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢
541 | * 如果你想为MJExtension输出代码,请拼命Pull Requests我
542 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - MJExtension (3.0.13)
3 |
4 | DEPENDENCIES:
5 | - MJExtension (~> 3.0.13)
6 |
7 | SPEC CHECKSUMS:
8 | MJExtension: 5932755f451458eefa24239358817f8d291240c7
9 |
10 | PODFILE CHECKSUM: de965e8f80782d615ad358bb6ce90846fd89d9fa
11 |
12 | COCOAPODS: 1.1.0.beta.1
13 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/MJExtension/MJExtension-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_MJExtension : NSObject
3 | @end
4 | @implementation PodsDummy_MJExtension
5 | @end
6 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/MJExtension/MJExtension-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #endif
4 |
5 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/MJExtension/MJExtension.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/MJExtension
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MJExtension" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MJExtension"
4 | PODS_BUILD_DIR = $BUILD_DIR
5 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
6 | PODS_ROOT = ${SRCROOT}
7 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
8 | SKIP_INSTALL = YES
9 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/Pods-ManageGroup/Pods-ManageGroup-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## MJExtension
5 |
6 | Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension)
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
26 | Generated by CocoaPods - https://cocoapods.org
27 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/Pods-ManageGroup/Pods-ManageGroup-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension)
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy
20 | of this software and associated documentation files (the "Software"), to deal
21 | in the Software without restriction, including without limitation the rights
22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 | copies of the Software, and to permit persons to whom the Software is
24 | furnished to do so, subject to the following conditions:
25 |
26 | The above copyright notice and this permission notice shall be included in
27 | all copies or substantial portions of the Software.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 | THE SOFTWARE.
36 |
37 | License
38 | MIT
39 | Title
40 | MJExtension
41 | Type
42 | PSGroupSpecifier
43 |
44 |
45 | FooterText
46 | Generated by CocoaPods - https://cocoapods.org
47 | Title
48 |
49 | Type
50 | PSGroupSpecifier
51 |
52 |
53 | StringsTable
54 | Acknowledgements
55 | Title
56 | Acknowledgements
57 |
58 |
59 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/Pods-ManageGroup/Pods-ManageGroup-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_ManageGroup : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_ManageGroup
5 | @end
6 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/Pods-ManageGroup/Pods-ManageGroup-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | install_framework()
10 | {
11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
12 | local source="${BUILT_PRODUCTS_DIR}/$1"
13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
15 | elif [ -r "$1" ]; then
16 | local source="$1"
17 | fi
18 |
19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
20 |
21 | if [ -L "${source}" ]; then
22 | echo "Symlinked..."
23 | source="$(readlink "${source}")"
24 | fi
25 |
26 | # use filter instead of exclude so missing patterns dont' throw errors
27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
29 |
30 | local basename
31 | basename="$(basename -s .framework "$1")"
32 | binary="${destination}/${basename}.framework/${basename}"
33 | if ! [ -r "$binary" ]; then
34 | binary="${destination}/${basename}"
35 | fi
36 |
37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
39 | strip_invalid_archs "$binary"
40 | fi
41 |
42 | # Resign the code if required by the build settings to avoid unstable apps
43 | code_sign_if_enabled "${destination}/$(basename "$1")"
44 |
45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
47 | local swift_runtime_libs
48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
49 | for lib in $swift_runtime_libs; do
50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
52 | code_sign_if_enabled "${destination}/${lib}"
53 | done
54 | fi
55 | }
56 |
57 | # Signs a framework with the provided identity
58 | code_sign_if_enabled() {
59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
60 | # Use the current code_sign_identitiy
61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\""
63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1"
64 | fi
65 | }
66 |
67 | # Strip invalid architectures
68 | strip_invalid_archs() {
69 | binary="$1"
70 | # Get architectures for current file
71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
72 | stripped=""
73 | for arch in $archs; do
74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
75 | # Strip non-valid architectures in-place
76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1
77 | stripped="$stripped $arch"
78 | fi
79 | done
80 | if [[ "$stripped" ]]; then
81 | echo "Stripped $binary of architectures:$stripped"
82 | fi
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/Pods-ManageGroup/Pods-ManageGroup-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | case "${TARGETED_DEVICE_FAMILY}" in
12 | 1,2)
13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
14 | ;;
15 | 1)
16 | TARGET_DEVICE_ARGS="--target-device iphone"
17 | ;;
18 | 2)
19 | TARGET_DEVICE_ARGS="--target-device ipad"
20 | ;;
21 | *)
22 | TARGET_DEVICE_ARGS="--target-device mac"
23 | ;;
24 | esac
25 |
26 | realpath() {
27 | DIRECTORY="$(cd "${1%/*}" && pwd)"
28 | FILENAME="${1##*/}"
29 | echo "$DIRECTORY/$FILENAME"
30 | }
31 |
32 | install_resource()
33 | {
34 | if [[ "$1" = /* ]] ; then
35 | RESOURCE_PATH="$1"
36 | else
37 | RESOURCE_PATH="${PODS_ROOT}/$1"
38 | fi
39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
40 | cat << EOM
41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
42 | EOM
43 | exit 1
44 | fi
45 | case $RESOURCE_PATH in
46 | *.storyboard)
47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
49 | ;;
50 | *.xib)
51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
53 | ;;
54 | *.framework)
55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
59 | ;;
60 | *.xcdatamodel)
61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\""
62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
63 | ;;
64 | *.xcdatamodeld)
65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\""
66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
67 | ;;
68 | *.xcmappingmodel)
69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\""
70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
71 | ;;
72 | *.xcassets)
73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH")
74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
75 | ;;
76 | *)
77 | echo "$RESOURCE_PATH"
78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
79 | ;;
80 | esac
81 | }
82 |
83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
88 | fi
89 | rm -f "$RESOURCES_TO_COPY"
90 |
91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
92 | then
93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
95 | while read line; do
96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
97 | XCASSET_FILES+=("$line")
98 | fi
99 | done <<<"$OTHER_XCASSETS"
100 |
101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
102 | fi
103 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/Pods-ManageGroup/Pods-ManageGroup.debug.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MJExtension"
3 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MJExtension"
4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/MJExtension"
5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"MJExtension"
6 | PODS_BUILD_DIR = $BUILD_DIR
7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}/Pods
9 |
--------------------------------------------------------------------------------
/ManageGroup/Pods/Target Support Files/Pods-ManageGroup/Pods-ManageGroup.release.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MJExtension"
3 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MJExtension"
4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/MJExtension"
5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"MJExtension"
6 | PODS_BUILD_DIR = $BUILD_DIR
7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}/Pods
9 |
--------------------------------------------------------------------------------
/ManageGroup/a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/a.png
--------------------------------------------------------------------------------
/ManageGroup/效果图.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiapp/ManageGroup/ce1a9bed7d1d8851167794c9261f00e6a761e547/ManageGroup/效果图.gif
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 项目说明
2 | 此DEMO抽取的是公司上线项目的管理联系人模块,使用的是MVC架构。如果觉得不错,希望各位大神支持一下😊
3 |
4 | # 效果图
5 |
6 | 
7 |
8 | # 项目结构
9 |
10 | 
11 |
12 | # 代码
13 |
14 | - 模拟网络请求,获取本地文件的内容,使用MJExtension将JSON转换成数据模型。
15 |
16 | ```json
17 | {
18 | "code": "1000",
19 | "ret_code": "0",
20 | "ret_msg": "操作成功",
21 | "groups": [
22 | {
23 | "group_id": "35ea5621962baa0e2b3dca2d4",
24 | "group_name": "未分组",
25 | "group_type": "1",
26 | "member_num": "3",
27 | "contacts": [
28 | {
29 | "id": "5848ead4d9e8d7b31172a285",
30 | "head_img": "default.png",
31 | "name": "张三",
32 | "description": "[WIFI在线] 欢迎给我留言",
33 | "active_time": "12:50"
34 | },
35 | {
36 | "id": "a243e23848ea43fddfs347b1",
37 | "head_img": "default.png",
38 | "name": "李四",
39 | "description": "[手机在线] 更新了日志",
40 | "active_time": "08:20"
41 | },
42 | {
43 | "id": "fsdfre522a43fddfs337b1",
44 | "head_img": "default.png",
45 | "name": "王五",
46 | "description": "[4G在线] 更新了说说",
47 | "active_time": "星期三"
48 | }
49 | ]
50 | },
51 | {
52 | "group_id": "80adasdas092dee232b74ca232",
53 | "group_name": "高中同学",
54 | "group_type": "2",
55 | "member_num": "2",
56 | "contacts": [
57 | {
58 | "id": "e323e65842ea43fd3sde367e4",
59 | "head_img": "default.png",
60 | "name": "小明",
61 | "description": "[电脑在线] 好好学习,天天向上",
62 | "active_time": "昨天"
63 | },
64 | {
65 | "id": "dwedwe3242cdw43fd3s3227e4",
66 | "head_img": "default.png",
67 | "name": "张小龙",
68 | "description": "[离线请留言] 哥是最牛逼的产品经理",
69 | "active_time": "2017/2/22"
70 | }
71 | ]
72 | },
73 | {
74 | "group_id": "dwe2357ec923e0e2b23a47",
75 | "group_name": "大学同学",
76 | "group_type": "2",
77 | "member_num": "1",
78 | "contacts": [
79 | {
80 | "id": "2dd4ddf65842dsd323d44fscsa21",
81 | "head_img": "default.png",
82 | "name": "乔布斯",
83 | "description": "[离线] 把产品做到极致",
84 | "active_time": "2017/2/22"
85 | }
86 | ]
87 | },
88 | {
89 | "group_id": "58ae5800963bee0e2b74ca48",
90 | "group_name": "同事",
91 | "group_type": "2",
92 | "member_num": "0"
93 | },
94 | {
95 | "group_id": "fdsds3233463bee0e2eeweffw",
96 | "group_name": "黑名单",
97 | "group_type": "2",
98 | "member_num": "0"
99 | }
100 | ]
101 | }
102 | ```
103 |
104 | - 指定哪些行的 cell 可以进行编辑 (UITableViewDataSource 协议方法)
105 |
106 | ```objective-c
107 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
108 | if (indexPath.row == 0) {
109 | return NO; // 第一行不能编辑
110 | } else {
111 | return YES;
112 | }
113 | }
114 | ```
115 |
116 | - 单元格返回的编辑风格(添加/删除/不可编辑,三种风格)(UITableViewDelegate协议中方法)
117 |
118 | ```
119 | - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
120 | return UITableViewCellEditingStyleDelete;
121 | }
122 | ```
123 |
124 | - 提交编辑状态/效果 (UITableViewDataSource协议中方法)
125 |
126 | ```objective-c
127 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
128 | //判断编辑状态是删除时 (点击 删除 按钮的操作)
129 | if (editingStyle == UITableViewCellEditingStyleDelete) {
130 | NSLog(@"删除分组!");
131 | }
132 | }
133 | ```
134 |
135 | - 移动分组
136 |
137 | ```objective-c
138 | /** 指定tableView那些行(cell)可以移动 */
139 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
140 | if (indexPath.row == 0) {
141 | return NO; //cell不能移动
142 | } else {
143 | return YES; //cell可以移动
144 | }
145 | }
146 | /** 移动cell后的操作:数据源进行更新 */
147 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
148 | //1. 存储将要被移动的位置的对象
149 | NSString *str = [_groupModelArr objectAtIndex:sourceIndexPath.row];
150 | //2. 将对象从原位置移除
151 | [self.groupModelArr removeObjectAtIndex:sourceIndexPath.row];
152 | //3. 将对象插入到新位置
153 | [self.groupModelArr insertObject:str atIndex:destinationIndexPath.row];
154 | //刷新表格
155 | [self.tableView reloadData];
156 | }
157 | ```
158 |
159 |
--------------------------------------------------------------------------------