├── .gitignore
├── ModelViewPresenterDemo
├── .idea
│ ├── .name
│ ├── ModelViewPresenterDemo.iml
│ ├── encodings.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── scopes
│ │ └── scope_settings.xml
│ ├── vcs.xml
│ ├── workspace.xml
│ └── xcode.xml
├── ModelViewPresenterDemo.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── dgadd.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata
│ │ └── dgadd.xcuserdatad
│ │ └── xcschemes
│ │ ├── All Tests.xcscheme
│ │ ├── ModelViewPresenterDemo.xcscheme
│ │ └── xcschememanagement.plist
├── ModelViewPresenterDemo
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── ModelViewPresenterDemo-Info.plist
│ ├── ModelViewPresenterDemo-Prefix.pch
│ ├── Presenters
│ │ ├── BookListPresenter.h
│ │ └── BookListPresenter.m
│ ├── Repositories
│ │ ├── FakeBookStoreRepository.h
│ │ ├── FakeBookStoreRepository.m
│ │ └── IBookStoreRepository.h
│ ├── ViewControllers
│ │ ├── DisplayBooksTableViewController.h
│ │ └── DisplayBooksTableViewController.m
│ ├── Views
│ │ └── IDisplayBooksView.h
│ ├── en.lproj
│ │ ├── InfoPlist.strings
│ │ ├── MainStoryboard_iPad.storyboard
│ │ └── MainStoryboard_iPhone.storyboard
│ └── main.m
├── ModelViewPresenterDemoTests
│ ├── BookListPresenterTests.h
│ ├── BookListPresenterTests.m
│ ├── ModelViewPresenterDemoTests-Info.plist
│ └── en.lproj
│ │ └── InfoPlist.strings
└── OCMocksLibs
│ ├── OCMock
│ ├── NSNotificationCenter+OCMAdditions.h
│ ├── OCMArg.h
│ ├── OCMConstraint.h
│ ├── OCMock.h
│ ├── OCMockObject.h
│ └── OCMockRecorder.h
│ └── libOCMock.a
└── README.markdown
/.gitignore:
--------------------------------------------------------------------------------
1 | #OS junk files
2 | [Tt]humbs.db
3 | *.DS_Store
4 |
5 | #Visual Studio files
6 | *.[Oo]bj
7 | *.exe
8 | *.pdb
9 | *.user
10 | *.aps
11 | # This file is required by C projects, so track it: *.pch
12 | *.vspscc
13 | *.vssscc
14 | *_i.c
15 | *_p.c
16 | *.ncb
17 | *.suo
18 | *.tlb
19 | *.tlh
20 | *.bak
21 | *.[Cc]ache
22 | *.ilk
23 | *.log
24 | *.lib
25 | *.sbr
26 | *.sdf
27 | ipch/
28 | obj/
29 | [Bb]in
30 | [Dd]ebug*/
31 | [Rr]elease*/
32 | Ankh.NoLoad
33 |
34 | #Tooling
35 | _ReSharper*/
36 | *.resharper
37 | [Tt]est[Rr]esult*
38 |
39 | #Project files
40 | [Bb]uild/
41 |
42 | #Subversion files
43 | .svn
44 |
45 | # Office Temp Files
46 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/.name:
--------------------------------------------------------------------------------
1 | ModelViewPresenterDemo
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/ModelViewPresenterDemo.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | http://www.w3.org/1999/xhtml
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | 1341709450042
167 | 1341709450042
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/.idea/xcode.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 72324F3E15A9102B0034CA8A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72324F3D15A9102B0034CA8A /* UIKit.framework */; };
11 | 72324F4015A9102B0034CA8A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72324F3F15A9102B0034CA8A /* Foundation.framework */; };
12 | 72324F4215A9102B0034CA8A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72324F4115A9102B0034CA8A /* CoreGraphics.framework */; };
13 | 72324F4815A9102B0034CA8A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 72324F4615A9102B0034CA8A /* InfoPlist.strings */; };
14 | 72324F4A15A9102B0034CA8A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 72324F4915A9102B0034CA8A /* main.m */; };
15 | 72324F4E15A9102B0034CA8A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 72324F4D15A9102B0034CA8A /* AppDelegate.m */; };
16 | 72324F5115A9102B0034CA8A /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 72324F4F15A9102B0034CA8A /* MainStoryboard_iPhone.storyboard */; };
17 | 72324F5415A9102B0034CA8A /* MainStoryboard_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 72324F5215A9102B0034CA8A /* MainStoryboard_iPad.storyboard */; };
18 | 72324F5F15A9102B0034CA8A /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72324F5E15A9102B0034CA8A /* SenTestingKit.framework */; };
19 | 72324F6015A9102B0034CA8A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72324F3D15A9102B0034CA8A /* UIKit.framework */; };
20 | 72324F6115A9102B0034CA8A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72324F3F15A9102B0034CA8A /* Foundation.framework */; };
21 | 72324F6915A9102B0034CA8A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 72324F6715A9102B0034CA8A /* InfoPlist.strings */; };
22 | 72324F7F15A910820034CA8A /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 72324F7715A910820034CA8A /* libOCMock.a */; };
23 | 72324F7F15A910820034CA8D /* BookListPresenterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 72324F7F15A910820034CA8C /* BookListPresenterTests.m */; };
24 | 72324F7F15A910820034CA92 /* BookListPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 72324F7F15A910820034CA91 /* BookListPresenter.m */; };
25 | 72324F7F15A910820034CA98 /* DisplayBooksTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72324F7F15A910820034CA97 /* DisplayBooksTableViewController.m */; };
26 | 72324F7F15A910820034CA9F /* FakeBookStoreRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = 72324F7F15A910820034CA9E /* FakeBookStoreRepository.m */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXContainerItemProxy section */
30 | 72324F6215A9102B0034CA8A /* PBXContainerItemProxy */ = {
31 | isa = PBXContainerItemProxy;
32 | containerPortal = 72324F3015A9102B0034CA8A /* Project object */;
33 | proxyType = 1;
34 | remoteGlobalIDString = 72324F3815A9102B0034CA8A;
35 | remoteInfo = ModelViewPresenterDemo;
36 | };
37 | /* End PBXContainerItemProxy section */
38 |
39 | /* Begin PBXFileReference section */
40 | 72324F3915A9102B0034CA8A /* ModelViewPresenterDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ModelViewPresenterDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 72324F3D15A9102B0034CA8A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
42 | 72324F3F15A9102B0034CA8A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
43 | 72324F4115A9102B0034CA8A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
44 | 72324F4515A9102B0034CA8A /* ModelViewPresenterDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ModelViewPresenterDemo-Info.plist"; sourceTree = ""; };
45 | 72324F4715A9102B0034CA8A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
46 | 72324F4915A9102B0034CA8A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
47 | 72324F4B15A9102B0034CA8A /* ModelViewPresenterDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ModelViewPresenterDemo-Prefix.pch"; sourceTree = ""; };
48 | 72324F4C15A9102B0034CA8A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
49 | 72324F4D15A9102B0034CA8A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
50 | 72324F5015A9102B0034CA8A /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPhone.storyboard; sourceTree = ""; };
51 | 72324F5315A9102B0034CA8A /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPad.storyboard; sourceTree = ""; };
52 | 72324F5D15A9102B0034CA8A /* ModelViewPresenterDemoTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ModelViewPresenterDemoTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
53 | 72324F5E15A9102B0034CA8A /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
54 | 72324F6615A9102B0034CA8A /* ModelViewPresenterDemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ModelViewPresenterDemoTests-Info.plist"; sourceTree = ""; };
55 | 72324F6815A9102B0034CA8A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
56 | 72324F7715A910820034CA8A /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = ""; };
57 | 72324F7915A910820034CA8A /* NSNotificationCenter+OCMAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+OCMAdditions.h"; sourceTree = ""; };
58 | 72324F7A15A910820034CA8A /* OCMArg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMArg.h; sourceTree = ""; };
59 | 72324F7B15A910820034CA8A /* OCMConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMConstraint.h; sourceTree = ""; };
60 | 72324F7C15A910820034CA8A /* OCMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMock.h; sourceTree = ""; };
61 | 72324F7D15A910820034CA8A /* OCMockObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMockObject.h; sourceTree = ""; };
62 | 72324F7E15A910820034CA8A /* OCMockRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMockRecorder.h; sourceTree = ""; };
63 | 72324F7F15A910820034CA8B /* BookListPresenterTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BookListPresenterTests.h; sourceTree = ""; };
64 | 72324F7F15A910820034CA8C /* BookListPresenterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BookListPresenterTests.m; sourceTree = ""; };
65 | 72324F7F15A910820034CA91 /* BookListPresenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BookListPresenter.m; sourceTree = ""; };
66 | 72324F7F15A910820034CA93 /* BookListPresenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BookListPresenter.h; sourceTree = ""; };
67 | 72324F7F15A910820034CA94 /* IDisplayBooksView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDisplayBooksView.h; sourceTree = ""; };
68 | 72324F7F15A910820034CA96 /* DisplayBooksTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayBooksTableViewController.h; sourceTree = ""; };
69 | 72324F7F15A910820034CA97 /* DisplayBooksTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DisplayBooksTableViewController.m; sourceTree = ""; };
70 | 72324F7F15A910820034CA9D /* IBookStoreRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IBookStoreRepository.h; sourceTree = ""; };
71 | 72324F7F15A910820034CA9E /* FakeBookStoreRepository.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FakeBookStoreRepository.m; sourceTree = ""; };
72 | 72324F7F15A910820034CAA0 /* FakeBookStoreRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FakeBookStoreRepository.h; sourceTree = ""; };
73 | /* End PBXFileReference section */
74 |
75 | /* Begin PBXFrameworksBuildPhase section */
76 | 72324F3615A9102B0034CA8A /* Frameworks */ = {
77 | isa = PBXFrameworksBuildPhase;
78 | buildActionMask = 2147483647;
79 | files = (
80 | 72324F3E15A9102B0034CA8A /* UIKit.framework in Frameworks */,
81 | 72324F4015A9102B0034CA8A /* Foundation.framework in Frameworks */,
82 | 72324F4215A9102B0034CA8A /* CoreGraphics.framework in Frameworks */,
83 | );
84 | runOnlyForDeploymentPostprocessing = 0;
85 | };
86 | 72324F5915A9102B0034CA8A /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | 72324F5F15A9102B0034CA8A /* SenTestingKit.framework in Frameworks */,
91 | 72324F6015A9102B0034CA8A /* UIKit.framework in Frameworks */,
92 | 72324F6115A9102B0034CA8A /* Foundation.framework in Frameworks */,
93 | 72324F7F15A910820034CA8A /* libOCMock.a in Frameworks */,
94 | );
95 | runOnlyForDeploymentPostprocessing = 0;
96 | };
97 | /* End PBXFrameworksBuildPhase section */
98 |
99 | /* Begin PBXGroup section */
100 | 72324F2E15A9102B0034CA8A = {
101 | isa = PBXGroup;
102 | children = (
103 | 72324F7515A910690034CA8A /* ThirdPartyLibs */,
104 | 72324F4315A9102B0034CA8A /* ModelViewPresenterDemo */,
105 | 72324F6415A9102B0034CA8A /* ModelViewPresenterDemoTests */,
106 | 72324F3C15A9102B0034CA8A /* Frameworks */,
107 | 72324F3A15A9102B0034CA8A /* Products */,
108 | );
109 | sourceTree = "";
110 | };
111 | 72324F3A15A9102B0034CA8A /* Products */ = {
112 | isa = PBXGroup;
113 | children = (
114 | 72324F3915A9102B0034CA8A /* ModelViewPresenterDemo.app */,
115 | 72324F5D15A9102B0034CA8A /* ModelViewPresenterDemoTests.octest */,
116 | );
117 | name = Products;
118 | sourceTree = "";
119 | };
120 | 72324F3C15A9102B0034CA8A /* Frameworks */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 72324F3D15A9102B0034CA8A /* UIKit.framework */,
124 | 72324F3F15A9102B0034CA8A /* Foundation.framework */,
125 | 72324F4115A9102B0034CA8A /* CoreGraphics.framework */,
126 | 72324F5E15A9102B0034CA8A /* SenTestingKit.framework */,
127 | );
128 | name = Frameworks;
129 | sourceTree = "";
130 | };
131 | 72324F4315A9102B0034CA8A /* ModelViewPresenterDemo */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 72324F4C15A9102B0034CA8A /* AppDelegate.h */,
135 | 72324F4D15A9102B0034CA8A /* AppDelegate.m */,
136 | 72324F4F15A9102B0034CA8A /* MainStoryboard_iPhone.storyboard */,
137 | 72324F5215A9102B0034CA8A /* MainStoryboard_iPad.storyboard */,
138 | 72324F4415A9102B0034CA8A /* Supporting Files */,
139 | 72324F7F15A910820034CA8E /* Presenters */,
140 | 72324F7F15A910820034CA8F /* Views */,
141 | 72324F7F15A910820034CA90 /* Models */,
142 | 72324F7F15A910820034CA95 /* ViewControllers */,
143 | 72324F7F15A910820034CA9C /* Repositories */,
144 | );
145 | path = ModelViewPresenterDemo;
146 | sourceTree = "";
147 | };
148 | 72324F4415A9102B0034CA8A /* Supporting Files */ = {
149 | isa = PBXGroup;
150 | children = (
151 | 72324F4515A9102B0034CA8A /* ModelViewPresenterDemo-Info.plist */,
152 | 72324F4615A9102B0034CA8A /* InfoPlist.strings */,
153 | 72324F4915A9102B0034CA8A /* main.m */,
154 | 72324F4B15A9102B0034CA8A /* ModelViewPresenterDemo-Prefix.pch */,
155 | );
156 | name = "Supporting Files";
157 | sourceTree = "";
158 | };
159 | 72324F6415A9102B0034CA8A /* ModelViewPresenterDemoTests */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 72324F7F15A910820034CA8C /* BookListPresenterTests.m */,
163 | 72324F7F15A910820034CA8B /* BookListPresenterTests.h */,
164 | 72324F6515A9102B0034CA8A /* Supporting Files */,
165 | );
166 | path = ModelViewPresenterDemoTests;
167 | sourceTree = "";
168 | };
169 | 72324F6515A9102B0034CA8A /* Supporting Files */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 72324F6615A9102B0034CA8A /* ModelViewPresenterDemoTests-Info.plist */,
173 | 72324F6715A9102B0034CA8A /* InfoPlist.strings */,
174 | );
175 | name = "Supporting Files";
176 | sourceTree = "";
177 | };
178 | 72324F7515A910690034CA8A /* ThirdPartyLibs */ = {
179 | isa = PBXGroup;
180 | children = (
181 | 72324F7615A910820034CA8A /* OCMocksLibs */,
182 | );
183 | name = ThirdPartyLibs;
184 | sourceTree = "";
185 | };
186 | 72324F7615A910820034CA8A /* OCMocksLibs */ = {
187 | isa = PBXGroup;
188 | children = (
189 | 72324F7715A910820034CA8A /* libOCMock.a */,
190 | 72324F7815A910820034CA8A /* OCMock */,
191 | );
192 | path = OCMocksLibs;
193 | sourceTree = "";
194 | };
195 | 72324F7815A910820034CA8A /* OCMock */ = {
196 | isa = PBXGroup;
197 | children = (
198 | 72324F7915A910820034CA8A /* NSNotificationCenter+OCMAdditions.h */,
199 | 72324F7A15A910820034CA8A /* OCMArg.h */,
200 | 72324F7B15A910820034CA8A /* OCMConstraint.h */,
201 | 72324F7C15A910820034CA8A /* OCMock.h */,
202 | 72324F7D15A910820034CA8A /* OCMockObject.h */,
203 | 72324F7E15A910820034CA8A /* OCMockRecorder.h */,
204 | );
205 | path = OCMock;
206 | sourceTree = "";
207 | };
208 | 72324F7F15A910820034CA8E /* Presenters */ = {
209 | isa = PBXGroup;
210 | children = (
211 | 72324F7F15A910820034CA93 /* BookListPresenter.h */,
212 | 72324F7F15A910820034CA91 /* BookListPresenter.m */,
213 | );
214 | path = Presenters;
215 | sourceTree = "";
216 | };
217 | 72324F7F15A910820034CA8F /* Views */ = {
218 | isa = PBXGroup;
219 | children = (
220 | 72324F7F15A910820034CA94 /* IDisplayBooksView.h */,
221 | );
222 | path = Views;
223 | sourceTree = "";
224 | };
225 | 72324F7F15A910820034CA90 /* Models */ = {
226 | isa = PBXGroup;
227 | children = (
228 | );
229 | path = Models;
230 | sourceTree = "";
231 | };
232 | 72324F7F15A910820034CA95 /* ViewControllers */ = {
233 | isa = PBXGroup;
234 | children = (
235 | 72324F7F15A910820034CA97 /* DisplayBooksTableViewController.m */,
236 | 72324F7F15A910820034CA96 /* DisplayBooksTableViewController.h */,
237 | );
238 | path = ViewControllers;
239 | sourceTree = "";
240 | };
241 | 72324F7F15A910820034CA9C /* Repositories */ = {
242 | isa = PBXGroup;
243 | children = (
244 | 72324F7F15A910820034CAA0 /* FakeBookStoreRepository.h */,
245 | 72324F7F15A910820034CA9E /* FakeBookStoreRepository.m */,
246 | 72324F7F15A910820034CA9D /* IBookStoreRepository.h */,
247 | );
248 | path = Repositories;
249 | sourceTree = "";
250 | };
251 | /* End PBXGroup section */
252 |
253 | /* Begin PBXNativeTarget section */
254 | 72324F3815A9102B0034CA8A /* ModelViewPresenterDemo */ = {
255 | isa = PBXNativeTarget;
256 | buildConfigurationList = 72324F6F15A9102B0034CA8A /* Build configuration list for PBXNativeTarget "ModelViewPresenterDemo" */;
257 | buildPhases = (
258 | 72324F3515A9102B0034CA8A /* Sources */,
259 | 72324F3615A9102B0034CA8A /* Frameworks */,
260 | 72324F3715A9102B0034CA8A /* Resources */,
261 | );
262 | buildRules = (
263 | );
264 | dependencies = (
265 | );
266 | name = ModelViewPresenterDemo;
267 | productName = ModelViewPresenterDemo;
268 | productReference = 72324F3915A9102B0034CA8A /* ModelViewPresenterDemo.app */;
269 | productType = "com.apple.product-type.application";
270 | };
271 | 72324F5C15A9102B0034CA8A /* ModelViewPresenterDemoTests */ = {
272 | isa = PBXNativeTarget;
273 | buildConfigurationList = 72324F7215A9102B0034CA8A /* Build configuration list for PBXNativeTarget "ModelViewPresenterDemoTests" */;
274 | buildPhases = (
275 | 72324F5815A9102B0034CA8A /* Sources */,
276 | 72324F5915A9102B0034CA8A /* Frameworks */,
277 | 72324F5A15A9102B0034CA8A /* Resources */,
278 | 72324F5B15A9102B0034CA8A /* ShellScript */,
279 | );
280 | buildRules = (
281 | );
282 | dependencies = (
283 | 72324F6315A9102B0034CA8A /* PBXTargetDependency */,
284 | );
285 | name = ModelViewPresenterDemoTests;
286 | productName = ModelViewPresenterDemoTests;
287 | productReference = 72324F5D15A9102B0034CA8A /* ModelViewPresenterDemoTests.octest */;
288 | productType = "com.apple.product-type.bundle";
289 | };
290 | /* End PBXNativeTarget section */
291 |
292 | /* Begin PBXProject section */
293 | 72324F3015A9102B0034CA8A /* Project object */ = {
294 | isa = PBXProject;
295 | attributes = {
296 | LastUpgradeCheck = 0430;
297 | };
298 | buildConfigurationList = 72324F3315A9102B0034CA8A /* Build configuration list for PBXProject "ModelViewPresenterDemo" */;
299 | compatibilityVersion = "Xcode 3.2";
300 | developmentRegion = English;
301 | hasScannedForEncodings = 0;
302 | knownRegions = (
303 | en,
304 | );
305 | mainGroup = 72324F2E15A9102B0034CA8A;
306 | productRefGroup = 72324F3A15A9102B0034CA8A /* Products */;
307 | projectDirPath = "";
308 | projectRoot = "";
309 | targets = (
310 | 72324F3815A9102B0034CA8A /* ModelViewPresenterDemo */,
311 | 72324F5C15A9102B0034CA8A /* ModelViewPresenterDemoTests */,
312 | );
313 | };
314 | /* End PBXProject section */
315 |
316 | /* Begin PBXResourcesBuildPhase section */
317 | 72324F3715A9102B0034CA8A /* Resources */ = {
318 | isa = PBXResourcesBuildPhase;
319 | buildActionMask = 2147483647;
320 | files = (
321 | 72324F4815A9102B0034CA8A /* InfoPlist.strings in Resources */,
322 | 72324F5115A9102B0034CA8A /* MainStoryboard_iPhone.storyboard in Resources */,
323 | 72324F5415A9102B0034CA8A /* MainStoryboard_iPad.storyboard in Resources */,
324 | );
325 | runOnlyForDeploymentPostprocessing = 0;
326 | };
327 | 72324F5A15A9102B0034CA8A /* Resources */ = {
328 | isa = PBXResourcesBuildPhase;
329 | buildActionMask = 2147483647;
330 | files = (
331 | 72324F6915A9102B0034CA8A /* InfoPlist.strings in Resources */,
332 | );
333 | runOnlyForDeploymentPostprocessing = 0;
334 | };
335 | /* End PBXResourcesBuildPhase section */
336 |
337 | /* Begin PBXShellScriptBuildPhase section */
338 | 72324F5B15A9102B0034CA8A /* ShellScript */ = {
339 | isa = PBXShellScriptBuildPhase;
340 | buildActionMask = 2147483647;
341 | files = (
342 | );
343 | inputPaths = (
344 | );
345 | outputPaths = (
346 | );
347 | runOnlyForDeploymentPostprocessing = 0;
348 | shellPath = /bin/sh;
349 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
350 | };
351 | /* End PBXShellScriptBuildPhase section */
352 |
353 | /* Begin PBXSourcesBuildPhase section */
354 | 72324F3515A9102B0034CA8A /* Sources */ = {
355 | isa = PBXSourcesBuildPhase;
356 | buildActionMask = 2147483647;
357 | files = (
358 | 72324F4A15A9102B0034CA8A /* main.m in Sources */,
359 | 72324F4E15A9102B0034CA8A /* AppDelegate.m in Sources */,
360 | 72324F7F15A910820034CA92 /* BookListPresenter.m in Sources */,
361 | 72324F7F15A910820034CA98 /* DisplayBooksTableViewController.m in Sources */,
362 | 72324F7F15A910820034CA9F /* FakeBookStoreRepository.m in Sources */,
363 | );
364 | runOnlyForDeploymentPostprocessing = 0;
365 | };
366 | 72324F5815A9102B0034CA8A /* Sources */ = {
367 | isa = PBXSourcesBuildPhase;
368 | buildActionMask = 2147483647;
369 | files = (
370 | 72324F7F15A910820034CA8D /* BookListPresenterTests.m in Sources */,
371 | );
372 | runOnlyForDeploymentPostprocessing = 0;
373 | };
374 | /* End PBXSourcesBuildPhase section */
375 |
376 | /* Begin PBXTargetDependency section */
377 | 72324F6315A9102B0034CA8A /* PBXTargetDependency */ = {
378 | isa = PBXTargetDependency;
379 | target = 72324F3815A9102B0034CA8A /* ModelViewPresenterDemo */;
380 | targetProxy = 72324F6215A9102B0034CA8A /* PBXContainerItemProxy */;
381 | };
382 | /* End PBXTargetDependency section */
383 |
384 | /* Begin PBXVariantGroup section */
385 | 72324F4615A9102B0034CA8A /* InfoPlist.strings */ = {
386 | isa = PBXVariantGroup;
387 | children = (
388 | 72324F4715A9102B0034CA8A /* en */,
389 | );
390 | name = InfoPlist.strings;
391 | sourceTree = "";
392 | };
393 | 72324F4F15A9102B0034CA8A /* MainStoryboard_iPhone.storyboard */ = {
394 | isa = PBXVariantGroup;
395 | children = (
396 | 72324F5015A9102B0034CA8A /* en */,
397 | );
398 | name = MainStoryboard_iPhone.storyboard;
399 | sourceTree = "";
400 | };
401 | 72324F5215A9102B0034CA8A /* MainStoryboard_iPad.storyboard */ = {
402 | isa = PBXVariantGroup;
403 | children = (
404 | 72324F5315A9102B0034CA8A /* en */,
405 | );
406 | name = MainStoryboard_iPad.storyboard;
407 | sourceTree = "";
408 | };
409 | 72324F6715A9102B0034CA8A /* InfoPlist.strings */ = {
410 | isa = PBXVariantGroup;
411 | children = (
412 | 72324F6815A9102B0034CA8A /* en */,
413 | );
414 | name = InfoPlist.strings;
415 | sourceTree = "";
416 | };
417 | /* End PBXVariantGroup section */
418 |
419 | /* Begin XCBuildConfiguration section */
420 | 72324F6D15A9102B0034CA8A /* Debug */ = {
421 | isa = XCBuildConfiguration;
422 | buildSettings = {
423 | ALWAYS_SEARCH_USER_PATHS = NO;
424 | ARCHS = "$(ARCHS_STANDARD_32_BIT)";
425 | CLANG_ENABLE_OBJC_ARC = YES;
426 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
427 | COPY_PHASE_STRIP = NO;
428 | GCC_C_LANGUAGE_STANDARD = gnu99;
429 | GCC_DYNAMIC_NO_PIC = NO;
430 | GCC_OPTIMIZATION_LEVEL = 0;
431 | GCC_PREPROCESSOR_DEFINITIONS = (
432 | "DEBUG=1",
433 | "$(inherited)",
434 | );
435 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
436 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
437 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
438 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
439 | GCC_WARN_UNUSED_VARIABLE = YES;
440 | IPHONEOS_DEPLOYMENT_TARGET = 5.1;
441 | SDKROOT = iphoneos;
442 | TARGETED_DEVICE_FAMILY = "1,2";
443 | };
444 | name = Debug;
445 | };
446 | 72324F6E15A9102B0034CA8A /* Release */ = {
447 | isa = XCBuildConfiguration;
448 | buildSettings = {
449 | ALWAYS_SEARCH_USER_PATHS = NO;
450 | ARCHS = "$(ARCHS_STANDARD_32_BIT)";
451 | CLANG_ENABLE_OBJC_ARC = YES;
452 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
453 | COPY_PHASE_STRIP = YES;
454 | GCC_C_LANGUAGE_STANDARD = gnu99;
455 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
456 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
457 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
458 | GCC_WARN_UNUSED_VARIABLE = YES;
459 | IPHONEOS_DEPLOYMENT_TARGET = 5.1;
460 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
461 | SDKROOT = iphoneos;
462 | TARGETED_DEVICE_FAMILY = "1,2";
463 | VALIDATE_PRODUCT = YES;
464 | };
465 | name = Release;
466 | };
467 | 72324F7015A9102B0034CA8A /* Debug */ = {
468 | isa = XCBuildConfiguration;
469 | buildSettings = {
470 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
471 | GCC_PREFIX_HEADER = "ModelViewPresenterDemo/ModelViewPresenterDemo-Prefix.pch";
472 | INFOPLIST_FILE = "ModelViewPresenterDemo/ModelViewPresenterDemo-Info.plist";
473 | PRODUCT_NAME = "$(TARGET_NAME)";
474 | WRAPPER_EXTENSION = app;
475 | };
476 | name = Debug;
477 | };
478 | 72324F7115A9102B0034CA8A /* Release */ = {
479 | isa = XCBuildConfiguration;
480 | buildSettings = {
481 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
482 | GCC_PREFIX_HEADER = "ModelViewPresenterDemo/ModelViewPresenterDemo-Prefix.pch";
483 | INFOPLIST_FILE = "ModelViewPresenterDemo/ModelViewPresenterDemo-Info.plist";
484 | PRODUCT_NAME = "$(TARGET_NAME)";
485 | WRAPPER_EXTENSION = app;
486 | };
487 | name = Release;
488 | };
489 | 72324F7315A9102B0034CA8A /* Debug */ = {
490 | isa = XCBuildConfiguration;
491 | buildSettings = {
492 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ModelViewPresenterDemo.app/ModelViewPresenterDemo";
493 | FRAMEWORK_SEARCH_PATHS = (
494 | "$(SDKROOT)/Developer/Library/Frameworks",
495 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks",
496 | );
497 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
498 | GCC_PREFIX_HEADER = "ModelViewPresenterDemo/ModelViewPresenterDemo-Prefix.pch";
499 | INFOPLIST_FILE = "ModelViewPresenterDemoTests/ModelViewPresenterDemoTests-Info.plist";
500 | LIBRARY_SEARCH_PATHS = (
501 | "$(inherited)",
502 | "\"$(SRCROOT)/OCMocksLibs\"",
503 | );
504 | "OTHER_LDFLAGS[arch=*]" = (
505 | "-force_load",
506 | OCMocksLibs/libOCMock.a,
507 | );
508 | PRODUCT_NAME = "$(TARGET_NAME)";
509 | TEST_HOST = "$(BUNDLE_LOADER)";
510 | WRAPPER_EXTENSION = octest;
511 | };
512 | name = Debug;
513 | };
514 | 72324F7415A9102B0034CA8A /* Release */ = {
515 | isa = XCBuildConfiguration;
516 | buildSettings = {
517 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ModelViewPresenterDemo.app/ModelViewPresenterDemo";
518 | FRAMEWORK_SEARCH_PATHS = (
519 | "$(SDKROOT)/Developer/Library/Frameworks",
520 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks",
521 | );
522 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
523 | GCC_PREFIX_HEADER = "ModelViewPresenterDemo/ModelViewPresenterDemo-Prefix.pch";
524 | INFOPLIST_FILE = "ModelViewPresenterDemoTests/ModelViewPresenterDemoTests-Info.plist";
525 | LIBRARY_SEARCH_PATHS = (
526 | "$(inherited)",
527 | "\"$(SRCROOT)/OCMocksLibs\"",
528 | );
529 | "OTHER_LDFLAGS[arch=*]" = (
530 | "-force_load",
531 | OCMocksLibs/libOCMock.a,
532 | );
533 | PRODUCT_NAME = "$(TARGET_NAME)";
534 | TEST_HOST = "$(BUNDLE_LOADER)";
535 | WRAPPER_EXTENSION = octest;
536 | };
537 | name = Release;
538 | };
539 | /* End XCBuildConfiguration section */
540 |
541 | /* Begin XCConfigurationList section */
542 | 72324F3315A9102B0034CA8A /* Build configuration list for PBXProject "ModelViewPresenterDemo" */ = {
543 | isa = XCConfigurationList;
544 | buildConfigurations = (
545 | 72324F6D15A9102B0034CA8A /* Debug */,
546 | 72324F6E15A9102B0034CA8A /* Release */,
547 | );
548 | defaultConfigurationIsVisible = 0;
549 | defaultConfigurationName = Release;
550 | };
551 | 72324F6F15A9102B0034CA8A /* Build configuration list for PBXNativeTarget "ModelViewPresenterDemo" */ = {
552 | isa = XCConfigurationList;
553 | buildConfigurations = (
554 | 72324F7015A9102B0034CA8A /* Debug */,
555 | 72324F7115A9102B0034CA8A /* Release */,
556 | );
557 | defaultConfigurationIsVisible = 0;
558 | defaultConfigurationName = Release;
559 | };
560 | 72324F7215A9102B0034CA8A /* Build configuration list for PBXNativeTarget "ModelViewPresenterDemoTests" */ = {
561 | isa = XCConfigurationList;
562 | buildConfigurations = (
563 | 72324F7315A9102B0034CA8A /* Debug */,
564 | 72324F7415A9102B0034CA8A /* Release */,
565 | );
566 | defaultConfigurationIsVisible = 0;
567 | defaultConfigurationName = Release;
568 | };
569 | /* End XCConfigurationList section */
570 | };
571 | rootObject = 72324F3015A9102B0034CA8A /* Project object */;
572 | }
573 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo.xcodeproj/project.xcworkspace/xcuserdata/dgadd.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgadd/iOSModelViewPresenter/d07d26b8f18073f0f917afef32f3b68fee194862/ModelViewPresenterDemo/ModelViewPresenterDemo.xcodeproj/project.xcworkspace/xcuserdata/dgadd.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo.xcodeproj/xcuserdata/dgadd.xcuserdatad/xcschemes/All Tests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
15 |
16 |
17 |
18 |
19 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
33 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo.xcodeproj/xcuserdata/dgadd.xcuserdatad/xcschemes/ModelViewPresenterDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
14 |
20 |
21 |
22 |
23 |
24 |
29 |
30 |
32 |
38 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
60 |
61 |
67 |
68 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo.xcodeproj/xcuserdata/dgadd.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ModelViewPresenterDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 72324F3815A9102B0034CA8A
16 |
17 | primary
18 |
19 |
20 | 72324F5C15A9102B0034CA8A
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ModelViewPresenterDemo
4 | //
5 | // Created by David Gadd on 12-07-07.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ModelViewPresenterDemo
4 | //
5 | // Created by David Gadd on 12-07-07.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @implementation AppDelegate
12 |
13 | @synthesize window = _window;
14 |
15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
16 | {
17 | // Override point for customization after application launch.
18 | return YES;
19 | }
20 |
21 | - (void)applicationWillResignActive:(UIApplication *)application
22 | {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | }
26 |
27 | - (void)applicationDidEnterBackground:(UIApplication *)application
28 | {
29 | // 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.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application
34 | {
35 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
36 | }
37 |
38 | - (void)applicationDidBecomeActive:(UIApplication *)application
39 | {
40 | // 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.
41 | }
42 |
43 | - (void)applicationWillTerminate:(UIApplication *)application
44 | {
45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/ModelViewPresenterDemo-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.gaddzeit.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UIMainStoryboardFile
28 | MainStoryboard_iPhone
29 | UIMainStoryboardFile~ipad
30 | MainStoryboard_iPad
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 | UISupportedInterfaceOrientations~ipad
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationPortraitUpsideDown
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/ModelViewPresenterDemo-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'ModelViewPresenterDemo' target in the 'ModelViewPresenterDemo' project
3 | //
4 |
5 | #import
6 |
7 | #ifndef __IPHONE_5_0
8 | #warning "This project uses features only available in iOS SDK 5.0 and later."
9 | #endif
10 |
11 | #ifdef __OBJC__
12 | #import
13 | #import
14 | #endif
15 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/Presenters/BookListPresenter.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @protocol IDisplayBooksView;
4 | @protocol IBookStoreRepository;
5 |
6 |
7 | @interface BookListPresenter : NSObject
8 | @property(nonatomic, strong) id displayBooksView;
9 | @property(nonatomic, strong) id bookStoreRepository;
10 |
11 | - (BookListPresenter *)initWithBookStoreRepository:(id )bookStoreRepository andDisplayBooksView:(id )displayBooksView;
12 |
13 | - (void)displayBooksFromBookstore;
14 | @end
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/Presenters/BookListPresenter.m:
--------------------------------------------------------------------------------
1 | #import "BookListPresenter.h"
2 | #import "IDisplayBooksView.h"
3 | #import "IBookStoreRepository.h"
4 |
5 |
6 | @implementation BookListPresenter {
7 |
8 | @private
9 | id _bookStoreRepository;
10 | }
11 | @synthesize displayBooksView = _displayBooksView;
12 | @synthesize bookStoreRepository = _bookStoreRepository;
13 |
14 |
15 | - (BookListPresenter *)initWithBookStoreRepository:(id )bookStoreRepository andDisplayBooksView:(id )displayBooksView {
16 | if (self = [super init]) {
17 | _bookStoreRepository = bookStoreRepository;
18 | _displayBooksView = displayBooksView;
19 | }
20 |
21 | return self;
22 | }
23 |
24 | - (void)displayBooksFromBookstore {
25 | NSArray *const books = [_bookStoreRepository findAllBooks];
26 | [_displayBooksView displayBooks:books];
27 | }
28 | @end
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/Repositories/FakeBookStoreRepository.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "IBookStoreRepository.h"
3 |
4 |
5 | @interface FakeBookStoreRepository : NSObject
6 | @end
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/Repositories/FakeBookStoreRepository.m:
--------------------------------------------------------------------------------
1 | #import "FakeBookStoreRepository.h"
2 |
3 |
4 | @implementation FakeBookStoreRepository {
5 |
6 |
7 | }
8 | - (NSArray *)findAllBooks {
9 | return [NSArray arrayWithObjects:@"Moby Dick",
10 | @"A Tale of Two Cities",
11 | @"Great Expectations",
12 | @"Absalom, Absalom",
13 | @"Cat's Eye",
14 | nil];
15 | }
16 |
17 |
18 | @end
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/Repositories/IBookStoreRepository.h:
--------------------------------------------------------------------------------
1 | @protocol IBookStoreRepository
2 |
3 | @required
4 | -(NSArray *)findAllBooks;
5 | @end
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/ViewControllers/DisplayBooksTableViewController.h:
--------------------------------------------------------------------------------
1 | #import "IDisplayBooksView.h"
2 |
3 | @interface DisplayBooksTableViewController : UITableViewController
4 |
5 | @property(nonatomic, strong) NSArray *books;
6 | @end
7 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/ViewControllers/DisplayBooksTableViewController.m:
--------------------------------------------------------------------------------
1 | #import "DisplayBooksTableViewController.h"
2 | #import "BookListPresenter.h"
3 | #import "IBookStoreRepository.h"
4 | #import "FakeBookStoreRepository.h"
5 |
6 | @interface DisplayBooksTableViewController ()
7 | - (BookListPresenter *)delegateDependencyInjectionToAnIocContainer;
8 |
9 |
10 | @end
11 |
12 | @implementation DisplayBooksTableViewController
13 | @synthesize books = _books;
14 |
15 |
16 | - (id)initWithStyle:(UITableViewStyle)style
17 | {
18 | self = [super initWithStyle:style];
19 | if (self) {
20 | // Custom initialization
21 | }
22 | return self;
23 | }
24 |
25 | - (void)displayBooks:(NSArray *)books {
26 | _books = books;
27 | }
28 |
29 | - (void)viewDidLoad {
30 | [super viewDidLoad];
31 | BookListPresenter *presenter = [self delegateDependencyInjectionToAnIocContainer];
32 | [presenter displayBooksFromBookstore];
33 | }
34 |
35 | - (void)viewDidUnload {
36 | [super viewDidUnload];
37 | }
38 |
39 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
40 | return (interfaceOrientation == UIInterfaceOrientationPortrait);
41 | }
42 |
43 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
44 | return 1;
45 | }
46 |
47 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
48 | return [_books count];
49 | }
50 |
51 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
52 | static NSString *CellIdentifier = @"BooksCell";
53 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
54 | [cell textLabel].text = [_books objectAtIndex:indexPath.row];
55 |
56 | return cell;
57 | }
58 |
59 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
60 | // do nothing
61 | }
62 |
63 | - (BookListPresenter *)delegateDependencyInjectionToAnIocContainer {
64 | id bookStoreRepository = [[FakeBookStoreRepository alloc] init];
65 | BookListPresenter *const presenter = [[BookListPresenter alloc] initWithBookStoreRepository:bookStoreRepository
66 | andDisplayBooksView:self];
67 | return presenter;
68 | }
69 |
70 |
71 | @end
72 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/Views/IDisplayBooksView.h:
--------------------------------------------------------------------------------
1 | @protocol IDisplayBooksView
2 |
3 | @required
4 | - (void)displayBooks:(NSArray*)books;
5 | @end
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/en.lproj/MainStoryboard_iPad.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 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/en.lproj/MainStoryboard_iPhone.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ModelViewPresenterDemo
4 | //
5 | // Created by David Gadd on 12-07-07.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "AppDelegate.h"
12 |
13 | int main(int argc, char *argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemoTests/BookListPresenterTests.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @class BookListPresenter;
4 |
5 | @interface BookListPresenterTests : SenTestCase {
6 | BookListPresenter *sut;
7 | }
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemoTests/BookListPresenterTests.m:
--------------------------------------------------------------------------------
1 | #import "BookListPresenterTests.h"
2 | #import "BookListPresenter.h"
3 | #import "OCMockObject.h"
4 | #import "IDisplayBooksView.h"
5 | #import "OCMockRecorder.h"
6 | #import "IBookStoreRepository.h"
7 | #import "FakeBookStoreRepository.h"
8 |
9 | @implementation BookListPresenterTests
10 |
11 | - (void)setUp {
12 | [super setUp];
13 | }
14 |
15 | - (void)testMockDisplayBooksFromBookStoreMethod_callToRepositoryToFindAll_booksAreBoundToView {
16 | NSArray* books = [NSArray arrayWithObjects:@"Moby Dick", @"The Grapes of Wrath", @"Tale of Two Cities", nil];
17 |
18 | id bookStoreRepository = [OCMockObject mockForProtocol:@protocol(IBookStoreRepository)];
19 | [[[bookStoreRepository expect] andReturn:books] findAllBooks];
20 |
21 | id displayBooksView = [OCMockObject mockForProtocol:@protocol(IDisplayBooksView)];
22 | [[displayBooksView expect] displayBooks:books];
23 |
24 | sut = [[BookListPresenter alloc] initWithBookStoreRepository:bookStoreRepository andDisplayBooksView:displayBooksView];
25 | [sut displayBooksFromBookstore];
26 |
27 |
28 | [bookStoreRepository verify];
29 | [displayBooksView verify];
30 | }
31 |
32 | - (void)testDisplayBooksFromBookStoreMethod_callToRepositoryToFindAll_booksAreBoundToView {
33 | NSArray*expectedBooks = [NSArray arrayWithObjects:@"Moby Dick",
34 | @"A Tale of Two Cities",
35 | @"Great Expectations",
36 | @"Absalom, Absalom",
37 | @"Cat's Eye",
38 | nil];
39 |
40 | id bookStoreRepository = [[FakeBookStoreRepository alloc] init];
41 | NSArray *const booksReturned = [bookStoreRepository findAllBooks];
42 |
43 | STAssertEqualObjects(expectedBooks, booksReturned, @"The books returned should match expected.");
44 | }
45 | @end
46 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemoTests/ModelViewPresenterDemoTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.gaddzeit.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/ModelViewPresenterDemoTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/OCMocksLibs/OCMock/NSNotificationCenter+OCMAdditions.h:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------------------------
2 | // $Id$
3 | // Copyright (c) 2009 by Mulle Kybernetik. See License file for details.
4 | //---------------------------------------------------------------------------------------
5 |
6 | #import
7 |
8 | @class OCMockObserver;
9 |
10 |
11 | @interface NSNotificationCenter(OCMAdditions)
12 |
13 | - (void)addMockObserver:(OCMockObserver *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/OCMocksLibs/OCMock/OCMArg.h:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------------------------
2 | // $Id$
3 | // Copyright (c) 2009-2010 by Mulle Kybernetik. See License file for details.
4 | //---------------------------------------------------------------------------------------
5 |
6 | #import
7 |
8 | @interface OCMArg : NSObject
9 |
10 | // constraining arguments
11 |
12 | + (id)any;
13 | + (void *)anyPointer;
14 | + (id)isNil;
15 | + (id)isNotNil;
16 | + (id)isNotEqual:(id)value;
17 | + (id)checkWithSelector:(SEL)selector onObject:(id)anObject;
18 | #if NS_BLOCKS_AVAILABLE
19 | + (id)checkWithBlock:(BOOL (^)(id))block;
20 | #endif
21 |
22 | // manipulating arguments
23 |
24 | + (id *)setTo:(id)value;
25 |
26 | // internal use only
27 |
28 | + (id)resolveSpecialValues:(NSValue *)value;
29 |
30 | @end
31 |
32 | #define OCMOCK_ANY [OCMArg any]
33 | #define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(__typeof__(variable))]
34 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/OCMocksLibs/OCMock/OCMConstraint.h:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------------------------
2 | // $Id$
3 | // Copyright (c) 2007-2010 by Mulle Kybernetik. See License file for details.
4 | //---------------------------------------------------------------------------------------
5 |
6 | #import
7 |
8 |
9 | @interface OCMConstraint : NSObject
10 |
11 | + (id)constraint;
12 | - (BOOL)evaluate:(id)value;
13 |
14 | // if you are looking for any, isNil, etc, they have moved to OCMArg
15 |
16 | // try to use [OCMArg checkWith...] instead of the constraintWith... methods below
17 |
18 | + (id)constraintWithSelector:(SEL)aSelector onObject:(id)anObject;
19 | + (id)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue;
20 |
21 |
22 | @end
23 |
24 | @interface OCMAnyConstraint : OCMConstraint
25 | @end
26 |
27 | @interface OCMIsNilConstraint : OCMConstraint
28 | @end
29 |
30 | @interface OCMIsNotNilConstraint : OCMConstraint
31 | @end
32 |
33 | @interface OCMIsNotEqualConstraint : OCMConstraint
34 | {
35 | @public
36 | id testValue;
37 | }
38 |
39 | @end
40 |
41 | @interface OCMInvocationConstraint : OCMConstraint
42 | {
43 | @public
44 | NSInvocation *invocation;
45 | }
46 |
47 | @end
48 |
49 | #if NS_BLOCKS_AVAILABLE
50 |
51 | @interface OCMBlockConstraint : OCMConstraint
52 | {
53 | BOOL (^block)(id);
54 | }
55 |
56 | - (id)initWithConstraintBlock:(BOOL (^)(id))block;
57 |
58 | @end
59 |
60 | #endif
61 |
62 |
63 | #define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self]
64 | #define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)]
65 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/OCMocksLibs/OCMock/OCMock.h:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------------------------
2 | // $Id$
3 | // Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details.
4 | //---------------------------------------------------------------------------------------
5 |
6 | #import
7 | #import
8 | #import
9 | #import
10 | #import
11 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/OCMocksLibs/OCMock/OCMockObject.h:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------------------------
2 | // $Id$
3 | // Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details.
4 | //---------------------------------------------------------------------------------------
5 |
6 | #import
7 |
8 | @interface OCMockObject : NSProxy
9 | {
10 | BOOL isNice;
11 | BOOL expectationOrderMatters;
12 | NSMutableArray *recorders;
13 | NSMutableArray *expectations;
14 | NSMutableArray *rejections;
15 | NSMutableArray *exceptions;
16 | }
17 |
18 | + (id)mockForClass:(Class)aClass;
19 | + (id)mockForProtocol:(Protocol *)aProtocol;
20 | + (id)partialMockForObject:(NSObject *)anObject;
21 |
22 | + (id)niceMockForClass:(Class)aClass;
23 | + (id)niceMockForProtocol:(Protocol *)aProtocol;
24 |
25 | + (id)observerMock;
26 |
27 | - (id)init;
28 |
29 | - (void)setExpectationOrderMatters:(BOOL)flag;
30 |
31 | - (id)stub;
32 | - (id)expect;
33 | - (id)reject;
34 |
35 | - (void)verify;
36 |
37 | // internal use only
38 |
39 | - (id)getNewRecorder;
40 | - (BOOL)handleInvocation:(NSInvocation *)anInvocation;
41 | - (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/OCMocksLibs/OCMock/OCMockRecorder.h:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------------------------
2 | // $Id$
3 | // Copyright (c) 2004-2010 by Mulle Kybernetik. See License file for details.
4 | //---------------------------------------------------------------------------------------
5 |
6 | #import
7 |
8 | @interface OCMockRecorder : NSProxy
9 | {
10 | id signatureResolver;
11 | NSInvocation *recordedInvocation;
12 | NSMutableArray *invocationHandlers;
13 | }
14 |
15 | - (id)initWithSignatureResolver:(id)anObject;
16 |
17 | - (BOOL)matchesInvocation:(NSInvocation *)anInvocation;
18 | - (void)releaseInvocation;
19 |
20 | - (id)andReturn:(id)anObject;
21 | - (id)andReturnValue:(NSValue *)aValue;
22 | - (id)andThrow:(NSException *)anException;
23 | - (id)andPost:(NSNotification *)aNotification;
24 | - (id)andCall:(SEL)selector onObject:(id)anObject;
25 | #if NS_BLOCKS_AVAILABLE
26 | - (id)andDo:(void (^)(NSInvocation *))block;
27 | #endif
28 | - (id)andForwardToRealObject;
29 |
30 | - (NSArray *)invocationHandlers;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/ModelViewPresenterDemo/OCMocksLibs/libOCMock.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dgadd/iOSModelViewPresenter/d07d26b8f18073f0f917afef32f3b68fee194862/ModelViewPresenterDemo/OCMocksLibs/libOCMock.a
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | Model-View-Presenter Example in iOS
2 |
3 |
4 | NOTE This sample code demonstrates only ONE method in the presenter class, a method to push an array of book titles to the view. In a typical, busy view controller with multiple events being handled, the underlying presenter class might have many methods to serve each of these activities.
5 |
6 |
7 |
8 | Over time, I will try and add additional presenter methods to this example.
9 |
10 |
11 |
12 |
13 | Explanation of Model-View-Presenter (used with protocols in iOS)
14 |
15 | MVP is a solution to the age-old problem of business logic and external coordination concerns slipping into the presentation layer. The view controllers in iOS are largely concerned with serving the view, either by listening for events and handling them (typically through delegate methods or IBAction methods), or by assigning information to properties. But it is difficult to prevent the rest of the application's concerns slipping into this layer by default.
16 |
17 |
18 |
19 | The best way to prevent this is by writing unit tests against the view controller. However, the view controller has many concerns and couplings that would make truly isolated unit-tests difficult.
20 |
21 |
22 |
23 | The Model-View-Presenter pattern addresses this by creating a new, simple class called a presenter, with no direct dependencies on any concerns above it (presentation) or below it (business logic, IO, data). The Presenter achieves this by only operating against protocols (interfaces in java/C#) which have been injected into the constructor (alloc/init) of the class. Unit tests use a combination of mock objects (that observe and verify behavior), stubs (simple auto-generated implementations of the protocol) or fully-created fake classes to verify the behavior of the presenter, without ever directly connecting to the view controller or underlying data sources.
24 |
25 |
26 |
27 | In this example code, the implementation of Model-View-Presenter uses:
28 |
29 | groups that store Presenters, Views, Models (and also: Repositories and ViewControllers)
30 | the Presenter init takes as parameters protocols (in Java and C#, this would be interfaces)
31 | the first parameter is a protocol for a repository (to query and return the Model)
32 | the second parameter is a protocol for the View (to receive content that is pushed to it, and to notify of events that it has received)
33 | the Model group is empty; the model in this implementation is merely an NSString* (a book title)
34 |
35 |
36 |
37 |
38 | The first unit test in this sample code uses mock objects to design and verify the behavior of the presenter methods. These methods coordinate the actions of the protocols that have been dependency-injected into the presenter's init. Specifically, the test verifies its expectation that the presenter's displayBooksFromBookstore method will:
39 |
40 | find all books from the book store repository
41 | "push" those books to the view
42 |
43 |
44 |
45 |
46 | The second unit test uses a fake class to verify that data passed through the presenter matches as expected.
47 |
48 |
49 |
50 | Finally: What should the view controller look like when Model-View-Presenter is used?
51 |
52 |
53 |
54 | It should have 4 main effects:
55 |
56 | An init or early event in the view controller should instantiate the presenter, passing in "self" as the conforming view protocol
57 | your view controller will still have lots of methods--filled with the event handling and delegate fulfilment methods that are typically required for an objective-C application. But the CONTENT of those methods will have changed.
58 | these methods should now contain only presentation logic. For example, the table row event will still have to retrieve the cell by its identifier and assign values to the cell's contents--those are a presentation-level concern
59 | but any non-presentation logic (coordination logic, business logic, model manipulation) will now be passed to presenter methods instead.
60 |
61 |
62 |
63 |
64 | And those presenter methods will now be isolated/decoupled and therefore can (and should) each be verified and validated by mock and unit tests.
65 |
--------------------------------------------------------------------------------