├── .gitignore ├── Articles.xcodeproj └── project.pbxproj ├── Articles ├── AppDelegate.h ├── AppDelegate.m ├── AppDelegate.m.trvs ├── Article.h ├── Article.m ├── ArticleList.h ├── ArticleList.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── DataModel.xcdatamodeld │ └── DataModel.xcdatamodel │ │ └── contents ├── DetailViewController.h ├── DetailViewController.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── MasterViewController.h ├── MasterViewController.m └── main.m ├── ArticlesTests ├── ArticlesTests.m └── Info.plist ├── Podfile ├── Podfile.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | # Pods - for those of you who use CocoaPods 19 | Pods -------------------------------------------------------------------------------- /Articles.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7F72B159BBAFB53C397E8A89 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BB6DF2E6A161FD02A4DD2A94 /* libPods.a */; }; 11 | D38B5D981A7FD5180064A6CE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D38B5D971A7FD5180064A6CE /* main.m */; }; 12 | D38B5D9B1A7FD5180064A6CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D38B5D9A1A7FD5180064A6CE /* AppDelegate.m */; }; 13 | D38B5D9E1A7FD5180064A6CE /* MasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D38B5D9D1A7FD5180064A6CE /* MasterViewController.m */; }; 14 | D38B5DA11A7FD5180064A6CE /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D38B5DA01A7FD5180064A6CE /* DetailViewController.m */; }; 15 | D38B5DA41A7FD5180064A6CE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D38B5DA21A7FD5180064A6CE /* Main.storyboard */; }; 16 | D38B5DA61A7FD5180064A6CE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D38B5DA51A7FD5180064A6CE /* Images.xcassets */; }; 17 | D38B5DA91A7FD5180064A6CE /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = D38B5DA71A7FD5180064A6CE /* LaunchScreen.xib */; }; 18 | D38B5DB51A7FD5180064A6CE /* ArticlesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D38B5DB41A7FD5180064A6CE /* ArticlesTests.m */; }; 19 | D38B5DC01A7FDA070064A6CE /* DataModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D38B5DBE1A7FDA070064A6CE /* DataModel.xcdatamodeld */; }; 20 | D3E03FDD1A80D81D00E133FD /* Article.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E03FDC1A80D81D00E133FD /* Article.m */; }; 21 | D3E03FE01A80D81E00E133FD /* ArticleList.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E03FDF1A80D81E00E133FD /* ArticleList.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | D38B5DAF1A7FD5180064A6CE /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = D38B5D8A1A7FD5180064A6CE /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = D38B5D911A7FD5180064A6CE; 30 | remoteInfo = Articles; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 13AF60A91A83096BE49EE44D /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 36 | 1853A936923D037EF8BDF191 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 37 | BB6DF2E6A161FD02A4DD2A94 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | D38B5D921A7FD5180064A6CE /* Articles.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Articles.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | D38B5D961A7FD5180064A6CE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | D38B5D971A7FD5180064A6CE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 41 | D38B5D991A7FD5180064A6CE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 42 | D38B5D9A1A7FD5180064A6CE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 43 | D38B5D9C1A7FD5180064A6CE /* MasterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MasterViewController.h; sourceTree = ""; }; 44 | D38B5D9D1A7FD5180064A6CE /* MasterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MasterViewController.m; sourceTree = ""; }; 45 | D38B5D9F1A7FD5180064A6CE /* DetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 46 | D38B5DA01A7FD5180064A6CE /* DetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 47 | D38B5DA31A7FD5180064A6CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 48 | D38B5DA51A7FD5180064A6CE /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 49 | D38B5DA81A7FD5180064A6CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 50 | D38B5DAE1A7FD5180064A6CE /* ArticlesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ArticlesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | D38B5DB31A7FD5180064A6CE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | D38B5DB41A7FD5180064A6CE /* ArticlesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ArticlesTests.m; sourceTree = ""; }; 53 | D38B5DBF1A7FDA070064A6CE /* DataModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = DataModel.xcdatamodel; sourceTree = ""; }; 54 | D3E03FDB1A80D81D00E133FD /* Article.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Article.h; sourceTree = ""; }; 55 | D3E03FDC1A80D81D00E133FD /* Article.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Article.m; sourceTree = ""; }; 56 | D3E03FDE1A80D81E00E133FD /* ArticleList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArticleList.h; sourceTree = ""; }; 57 | D3E03FDF1A80D81E00E133FD /* ArticleList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArticleList.m; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | D38B5D8F1A7FD5180064A6CE /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | 7F72B159BBAFB53C397E8A89 /* libPods.a in Frameworks */, 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | D38B5DAB1A7FD5180064A6CE /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 3297C3A75987D07EDDF933C2 /* Pods */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 13AF60A91A83096BE49EE44D /* Pods.debug.xcconfig */, 83 | 1853A936923D037EF8BDF191 /* Pods.release.xcconfig */, 84 | ); 85 | name = Pods; 86 | sourceTree = ""; 87 | }; 88 | 549B0847F0BBDC67DFA32EDD /* Frameworks */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | BB6DF2E6A161FD02A4DD2A94 /* libPods.a */, 92 | ); 93 | name = Frameworks; 94 | sourceTree = ""; 95 | }; 96 | D38B5D891A7FD5180064A6CE = { 97 | isa = PBXGroup; 98 | children = ( 99 | D38B5D941A7FD5180064A6CE /* Articles */, 100 | D38B5DB11A7FD5180064A6CE /* ArticlesTests */, 101 | D38B5D931A7FD5180064A6CE /* Products */, 102 | 3297C3A75987D07EDDF933C2 /* Pods */, 103 | 549B0847F0BBDC67DFA32EDD /* Frameworks */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | D38B5D931A7FD5180064A6CE /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | D38B5D921A7FD5180064A6CE /* Articles.app */, 111 | D38B5DAE1A7FD5180064A6CE /* ArticlesTests.xctest */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | D38B5D941A7FD5180064A6CE /* Articles */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | D38B5D991A7FD5180064A6CE /* AppDelegate.h */, 120 | D38B5D9A1A7FD5180064A6CE /* AppDelegate.m */, 121 | D38B5D9C1A7FD5180064A6CE /* MasterViewController.h */, 122 | D38B5D9D1A7FD5180064A6CE /* MasterViewController.m */, 123 | D38B5D9F1A7FD5180064A6CE /* DetailViewController.h */, 124 | D38B5DA01A7FD5180064A6CE /* DetailViewController.m */, 125 | D38B5DA21A7FD5180064A6CE /* Main.storyboard */, 126 | D38B5DA51A7FD5180064A6CE /* Images.xcassets */, 127 | D38B5DA71A7FD5180064A6CE /* LaunchScreen.xib */, 128 | D38B5D951A7FD5180064A6CE /* Supporting Files */, 129 | D38B5DBE1A7FDA070064A6CE /* DataModel.xcdatamodeld */, 130 | D3E03FDE1A80D81E00E133FD /* ArticleList.h */, 131 | D3E03FDF1A80D81E00E133FD /* ArticleList.m */, 132 | D3E03FDB1A80D81D00E133FD /* Article.h */, 133 | D3E03FDC1A80D81D00E133FD /* Article.m */, 134 | ); 135 | path = Articles; 136 | sourceTree = ""; 137 | }; 138 | D38B5D951A7FD5180064A6CE /* Supporting Files */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | D38B5D961A7FD5180064A6CE /* Info.plist */, 142 | D38B5D971A7FD5180064A6CE /* main.m */, 143 | ); 144 | name = "Supporting Files"; 145 | sourceTree = ""; 146 | }; 147 | D38B5DB11A7FD5180064A6CE /* ArticlesTests */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | D38B5DB41A7FD5180064A6CE /* ArticlesTests.m */, 151 | D38B5DB21A7FD5180064A6CE /* Supporting Files */, 152 | ); 153 | path = ArticlesTests; 154 | sourceTree = ""; 155 | }; 156 | D38B5DB21A7FD5180064A6CE /* Supporting Files */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | D38B5DB31A7FD5180064A6CE /* Info.plist */, 160 | ); 161 | name = "Supporting Files"; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | D38B5D911A7FD5180064A6CE /* Articles */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = D38B5DB81A7FD5180064A6CE /* Build configuration list for PBXNativeTarget "Articles" */; 170 | buildPhases = ( 171 | 6A319AF0B5B60B8F48EDE484 /* Check Pods Manifest.lock */, 172 | D38B5D8E1A7FD5180064A6CE /* Sources */, 173 | D38B5D8F1A7FD5180064A6CE /* Frameworks */, 174 | D38B5D901A7FD5180064A6CE /* Resources */, 175 | B5C6F9B9E68EC282942653B6 /* Copy Pods Resources */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | ); 181 | name = Articles; 182 | productName = Articles; 183 | productReference = D38B5D921A7FD5180064A6CE /* Articles.app */; 184 | productType = "com.apple.product-type.application"; 185 | }; 186 | D38B5DAD1A7FD5180064A6CE /* ArticlesTests */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = D38B5DBB1A7FD5180064A6CE /* Build configuration list for PBXNativeTarget "ArticlesTests" */; 189 | buildPhases = ( 190 | D38B5DAA1A7FD5180064A6CE /* Sources */, 191 | D38B5DAB1A7FD5180064A6CE /* Frameworks */, 192 | D38B5DAC1A7FD5180064A6CE /* Resources */, 193 | ); 194 | buildRules = ( 195 | ); 196 | dependencies = ( 197 | D38B5DB01A7FD5180064A6CE /* PBXTargetDependency */, 198 | ); 199 | name = ArticlesTests; 200 | productName = ArticlesTests; 201 | productReference = D38B5DAE1A7FD5180064A6CE /* ArticlesTests.xctest */; 202 | productType = "com.apple.product-type.bundle.unit-test"; 203 | }; 204 | /* End PBXNativeTarget section */ 205 | 206 | /* Begin PBXProject section */ 207 | D38B5D8A1A7FD5180064A6CE /* Project object */ = { 208 | isa = PBXProject; 209 | attributes = { 210 | LastUpgradeCheck = 0610; 211 | ORGANIZATIONNAME = Marcin; 212 | TargetAttributes = { 213 | D38B5D911A7FD5180064A6CE = { 214 | CreatedOnToolsVersion = 6.1; 215 | }; 216 | D38B5DAD1A7FD5180064A6CE = { 217 | CreatedOnToolsVersion = 6.1; 218 | TestTargetID = D38B5D911A7FD5180064A6CE; 219 | }; 220 | }; 221 | }; 222 | buildConfigurationList = D38B5D8D1A7FD5180064A6CE /* Build configuration list for PBXProject "Articles" */; 223 | compatibilityVersion = "Xcode 3.2"; 224 | developmentRegion = English; 225 | hasScannedForEncodings = 0; 226 | knownRegions = ( 227 | en, 228 | Base, 229 | ); 230 | mainGroup = D38B5D891A7FD5180064A6CE; 231 | productRefGroup = D38B5D931A7FD5180064A6CE /* Products */; 232 | projectDirPath = ""; 233 | projectRoot = ""; 234 | targets = ( 235 | D38B5D911A7FD5180064A6CE /* Articles */, 236 | D38B5DAD1A7FD5180064A6CE /* ArticlesTests */, 237 | ); 238 | }; 239 | /* End PBXProject section */ 240 | 241 | /* Begin PBXResourcesBuildPhase section */ 242 | D38B5D901A7FD5180064A6CE /* Resources */ = { 243 | isa = PBXResourcesBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | D38B5DA41A7FD5180064A6CE /* Main.storyboard in Resources */, 247 | D38B5DA91A7FD5180064A6CE /* LaunchScreen.xib in Resources */, 248 | D38B5DA61A7FD5180064A6CE /* Images.xcassets in Resources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | D38B5DAC1A7FD5180064A6CE /* Resources */ = { 253 | isa = PBXResourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | /* End PBXResourcesBuildPhase section */ 260 | 261 | /* Begin PBXShellScriptBuildPhase section */ 262 | 6A319AF0B5B60B8F48EDE484 /* Check Pods Manifest.lock */ = { 263 | isa = PBXShellScriptBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | ); 267 | inputPaths = ( 268 | ); 269 | name = "Check Pods Manifest.lock"; 270 | outputPaths = ( 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | shellPath = /bin/sh; 274 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 275 | showEnvVarsInLog = 0; 276 | }; 277 | B5C6F9B9E68EC282942653B6 /* Copy Pods Resources */ = { 278 | isa = PBXShellScriptBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | ); 282 | inputPaths = ( 283 | ); 284 | name = "Copy Pods Resources"; 285 | outputPaths = ( 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | shellPath = /bin/sh; 289 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 290 | showEnvVarsInLog = 0; 291 | }; 292 | /* End PBXShellScriptBuildPhase section */ 293 | 294 | /* Begin PBXSourcesBuildPhase section */ 295 | D38B5D8E1A7FD5180064A6CE /* Sources */ = { 296 | isa = PBXSourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | D38B5D9B1A7FD5180064A6CE /* AppDelegate.m in Sources */, 300 | D38B5DC01A7FDA070064A6CE /* DataModel.xcdatamodeld in Sources */, 301 | D3E03FDD1A80D81D00E133FD /* Article.m in Sources */, 302 | D3E03FE01A80D81E00E133FD /* ArticleList.m in Sources */, 303 | D38B5D9E1A7FD5180064A6CE /* MasterViewController.m in Sources */, 304 | D38B5D981A7FD5180064A6CE /* main.m in Sources */, 305 | D38B5DA11A7FD5180064A6CE /* DetailViewController.m in Sources */, 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | D38B5DAA1A7FD5180064A6CE /* Sources */ = { 310 | isa = PBXSourcesBuildPhase; 311 | buildActionMask = 2147483647; 312 | files = ( 313 | D38B5DB51A7FD5180064A6CE /* ArticlesTests.m in Sources */, 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | /* End PBXSourcesBuildPhase section */ 318 | 319 | /* Begin PBXTargetDependency section */ 320 | D38B5DB01A7FD5180064A6CE /* PBXTargetDependency */ = { 321 | isa = PBXTargetDependency; 322 | target = D38B5D911A7FD5180064A6CE /* Articles */; 323 | targetProxy = D38B5DAF1A7FD5180064A6CE /* PBXContainerItemProxy */; 324 | }; 325 | /* End PBXTargetDependency section */ 326 | 327 | /* Begin PBXVariantGroup section */ 328 | D38B5DA21A7FD5180064A6CE /* Main.storyboard */ = { 329 | isa = PBXVariantGroup; 330 | children = ( 331 | D38B5DA31A7FD5180064A6CE /* Base */, 332 | ); 333 | name = Main.storyboard; 334 | sourceTree = ""; 335 | }; 336 | D38B5DA71A7FD5180064A6CE /* LaunchScreen.xib */ = { 337 | isa = PBXVariantGroup; 338 | children = ( 339 | D38B5DA81A7FD5180064A6CE /* Base */, 340 | ); 341 | name = LaunchScreen.xib; 342 | sourceTree = ""; 343 | }; 344 | /* End PBXVariantGroup section */ 345 | 346 | /* Begin XCBuildConfiguration section */ 347 | D38B5DB61A7FD5180064A6CE /* Debug */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | ALWAYS_SEARCH_USER_PATHS = NO; 351 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 352 | CLANG_CXX_LIBRARY = "libc++"; 353 | CLANG_ENABLE_MODULES = YES; 354 | CLANG_ENABLE_OBJC_ARC = YES; 355 | CLANG_WARN_BOOL_CONVERSION = YES; 356 | CLANG_WARN_CONSTANT_CONVERSION = YES; 357 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 358 | CLANG_WARN_EMPTY_BODY = YES; 359 | CLANG_WARN_ENUM_CONVERSION = YES; 360 | CLANG_WARN_INT_CONVERSION = YES; 361 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 362 | CLANG_WARN_UNREACHABLE_CODE = YES; 363 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 364 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 365 | COPY_PHASE_STRIP = NO; 366 | ENABLE_STRICT_OBJC_MSGSEND = YES; 367 | GCC_C_LANGUAGE_STANDARD = gnu99; 368 | GCC_DYNAMIC_NO_PIC = NO; 369 | GCC_OPTIMIZATION_LEVEL = 0; 370 | GCC_PREPROCESSOR_DEFINITIONS = ( 371 | "DEBUG=1", 372 | "$(inherited)", 373 | ); 374 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 375 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 376 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 377 | GCC_WARN_UNDECLARED_SELECTOR = YES; 378 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 379 | GCC_WARN_UNUSED_FUNCTION = YES; 380 | GCC_WARN_UNUSED_VARIABLE = YES; 381 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 382 | MTL_ENABLE_DEBUG_INFO = YES; 383 | ONLY_ACTIVE_ARCH = YES; 384 | SDKROOT = iphoneos; 385 | }; 386 | name = Debug; 387 | }; 388 | D38B5DB71A7FD5180064A6CE /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | ALWAYS_SEARCH_USER_PATHS = NO; 392 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 393 | CLANG_CXX_LIBRARY = "libc++"; 394 | CLANG_ENABLE_MODULES = YES; 395 | CLANG_ENABLE_OBJC_ARC = YES; 396 | CLANG_WARN_BOOL_CONVERSION = YES; 397 | CLANG_WARN_CONSTANT_CONVERSION = YES; 398 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 399 | CLANG_WARN_EMPTY_BODY = YES; 400 | CLANG_WARN_ENUM_CONVERSION = YES; 401 | CLANG_WARN_INT_CONVERSION = YES; 402 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 403 | CLANG_WARN_UNREACHABLE_CODE = YES; 404 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 405 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 406 | COPY_PHASE_STRIP = YES; 407 | ENABLE_NS_ASSERTIONS = NO; 408 | ENABLE_STRICT_OBJC_MSGSEND = YES; 409 | GCC_C_LANGUAGE_STANDARD = gnu99; 410 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 411 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 412 | GCC_WARN_UNDECLARED_SELECTOR = YES; 413 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 414 | GCC_WARN_UNUSED_FUNCTION = YES; 415 | GCC_WARN_UNUSED_VARIABLE = YES; 416 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 417 | MTL_ENABLE_DEBUG_INFO = NO; 418 | SDKROOT = iphoneos; 419 | VALIDATE_PRODUCT = YES; 420 | }; 421 | name = Release; 422 | }; 423 | D38B5DB91A7FD5180064A6CE /* Debug */ = { 424 | isa = XCBuildConfiguration; 425 | baseConfigurationReference = 13AF60A91A83096BE49EE44D /* Pods.debug.xcconfig */; 426 | buildSettings = { 427 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 428 | INFOPLIST_FILE = Articles/Info.plist; 429 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 430 | PRODUCT_NAME = "$(TARGET_NAME)"; 431 | }; 432 | name = Debug; 433 | }; 434 | D38B5DBA1A7FD5180064A6CE /* Release */ = { 435 | isa = XCBuildConfiguration; 436 | baseConfigurationReference = 1853A936923D037EF8BDF191 /* Pods.release.xcconfig */; 437 | buildSettings = { 438 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 439 | INFOPLIST_FILE = Articles/Info.plist; 440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 441 | PRODUCT_NAME = "$(TARGET_NAME)"; 442 | }; 443 | name = Release; 444 | }; 445 | D38B5DBC1A7FD5180064A6CE /* Debug */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | BUNDLE_LOADER = "$(TEST_HOST)"; 449 | FRAMEWORK_SEARCH_PATHS = ( 450 | "$(SDKROOT)/Developer/Library/Frameworks", 451 | "$(inherited)", 452 | ); 453 | GCC_PREPROCESSOR_DEFINITIONS = ( 454 | "DEBUG=1", 455 | "$(inherited)", 456 | ); 457 | INFOPLIST_FILE = ArticlesTests/Info.plist; 458 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 459 | PRODUCT_NAME = "$(TARGET_NAME)"; 460 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Articles.app/Articles"; 461 | }; 462 | name = Debug; 463 | }; 464 | D38B5DBD1A7FD5180064A6CE /* Release */ = { 465 | isa = XCBuildConfiguration; 466 | buildSettings = { 467 | BUNDLE_LOADER = "$(TEST_HOST)"; 468 | FRAMEWORK_SEARCH_PATHS = ( 469 | "$(SDKROOT)/Developer/Library/Frameworks", 470 | "$(inherited)", 471 | ); 472 | INFOPLIST_FILE = ArticlesTests/Info.plist; 473 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 474 | PRODUCT_NAME = "$(TARGET_NAME)"; 475 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Articles.app/Articles"; 476 | }; 477 | name = Release; 478 | }; 479 | /* End XCBuildConfiguration section */ 480 | 481 | /* Begin XCConfigurationList section */ 482 | D38B5D8D1A7FD5180064A6CE /* Build configuration list for PBXProject "Articles" */ = { 483 | isa = XCConfigurationList; 484 | buildConfigurations = ( 485 | D38B5DB61A7FD5180064A6CE /* Debug */, 486 | D38B5DB71A7FD5180064A6CE /* Release */, 487 | ); 488 | defaultConfigurationIsVisible = 0; 489 | defaultConfigurationName = Release; 490 | }; 491 | D38B5DB81A7FD5180064A6CE /* Build configuration list for PBXNativeTarget "Articles" */ = { 492 | isa = XCConfigurationList; 493 | buildConfigurations = ( 494 | D38B5DB91A7FD5180064A6CE /* Debug */, 495 | D38B5DBA1A7FD5180064A6CE /* Release */, 496 | ); 497 | defaultConfigurationIsVisible = 0; 498 | defaultConfigurationName = Release; 499 | }; 500 | D38B5DBB1A7FD5180064A6CE /* Build configuration list for PBXNativeTarget "ArticlesTests" */ = { 501 | isa = XCConfigurationList; 502 | buildConfigurations = ( 503 | D38B5DBC1A7FD5180064A6CE /* Debug */, 504 | D38B5DBD1A7FD5180064A6CE /* Release */, 505 | ); 506 | defaultConfigurationIsVisible = 0; 507 | defaultConfigurationName = Release; 508 | }; 509 | /* End XCConfigurationList section */ 510 | 511 | /* Begin XCVersionGroup section */ 512 | D38B5DBE1A7FDA070064A6CE /* DataModel.xcdatamodeld */ = { 513 | isa = XCVersionGroup; 514 | children = ( 515 | D38B5DBF1A7FDA070064A6CE /* DataModel.xcdatamodel */, 516 | ); 517 | currentVersion = D38B5DBF1A7FDA070064A6CE /* DataModel.xcdatamodel */; 518 | path = DataModel.xcdatamodeld; 519 | sourceTree = ""; 520 | versionGroupType = wrapper.xcdatamodel; 521 | }; 522 | /* End XCVersionGroup section */ 523 | }; 524 | rootObject = D38B5D8A1A7FD5180064A6CE /* Project object */; 525 | } 526 | -------------------------------------------------------------------------------- /Articles/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. 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 | -------------------------------------------------------------------------------- /Articles/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "DetailViewController.h" 11 | 12 | #import 13 | #import 14 | 15 | @interface AppDelegate () 16 | 17 | @end 18 | 19 | @implementation AppDelegate 20 | 21 | 22 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 23 | // Initialize RestKit 24 | NSURL *baseURL = [NSURL URLWithString:@"http://api.feedzilla.com"]; 25 | RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL]; 26 | 27 | 28 | // Initialize managed object model from bundle 29 | NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; 30 | // Initialize managed object store 31 | RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; 32 | objectManager.managedObjectStore = managedObjectStore; 33 | 34 | 35 | // Complete Core Data stack initialization 36 | [managedObjectStore createPersistentStoreCoordinator]; 37 | NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"ArticlesDB.sqlite"]; 38 | NSString *seedPath = [[NSBundle mainBundle] pathForResource:@"RKSeedDatabase" ofType:@"sqlite"]; 39 | NSError *error; 40 | NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:seedPath withConfiguration:nil options:nil error:&error]; 41 | NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error); 42 | 43 | // Create the managed object contexts 44 | [managedObjectStore createManagedObjectContexts]; 45 | 46 | // Configure a managed object cache to ensure we do not create duplicate objects 47 | managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; 48 | 49 | RKEntityMapping *articleListMapping = [RKEntityMapping mappingForEntityForName:@"ArticleList" inManagedObjectStore:managedObjectStore]; 50 | articleListMapping.identificationAttributes = @[@"title"]; 51 | [articleListMapping addAttributeMappingsFromDictionary:@{ @"title" : @"title", @"syndication_url" : @"url", @"description" : @"article_description" }]; 52 | 53 | RKEntityMapping *articleMapping = [RKEntityMapping mappingForEntityForName:@"Article" inManagedObjectStore:managedObjectStore]; 54 | articleMapping.identificationAttributes = @[@"source_url"]; 55 | [articleMapping addAttributeMappingsFromArray:@[@"publish_date", @"source", @"source_url", @"summary", @"title", @"url"]]; 56 | 57 | [articleListMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"articles" toKeyPath:@"articles" withMapping:articleMapping]]; 58 | 59 | // Register article mapping with the provider 60 | RKResponseDescriptor *articleListResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:articleListMapping 61 | method:RKRequestMethodGET 62 | pathPattern:@"/v1/categories/:id/articles.json" 63 | keyPath:nil 64 | statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; 65 | [objectManager addResponseDescriptor:articleListResponseDescriptor]; 66 | 67 | // Enable Activity Indicator Spinner 68 | [AFNetworkActivityIndicatorManager sharedManager].enabled = YES; 69 | 70 | return YES; 71 | } 72 | 73 | - (void)applicationWillResignActive:(UIApplication *)application { 74 | // 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. 75 | // 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. 76 | } 77 | 78 | - (void)applicationDidEnterBackground:(UIApplication *)application { 79 | // 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. 80 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 81 | } 82 | 83 | - (void)applicationWillEnterForeground:(UIApplication *)application { 84 | // 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. 85 | } 86 | 87 | - (void)applicationDidBecomeActive:(UIApplication *)application { 88 | // 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. 89 | } 90 | 91 | - (void)applicationWillTerminate:(UIApplication *)application { 92 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /Articles/AppDelegate.m.trvs: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "DetailViewController.h" 11 | 12 | #import 13 | #import 14 | 15 | @interface AppDelegate () 16 | 17 | @end 18 | 19 | @implementation AppDelegate 20 | 21 | - (BOOL)application:(UIApplication *)application 22 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 23 | // Initialize RestKit 24 | NSURL *baseURL = [NSURL URLWithString:@"http://api.feedzilla.com"]; 25 | RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL]; 26 | 27 | // Initialize managed object model from bundle 28 | NSManagedObjectModel *managedObjectModel = 29 | [NSManagedObjectModel mergedModelFromBundles:nil]; 30 | // Initialize managed object store 31 | RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] 32 | initWithManagedObjectModel:managedObjectModel]; 33 | objectManager.managedObjectStore = managedObjectStore; 34 | 35 | // Complete Core Data stack initialization 36 | [managedObjectStore createPersistentStoreCoordinator]; 37 | NSString *storePath = [RKApplicationDataDirectory() 38 | stringByAppendingPathComponent:@"ArticlesDB.sqlite"]; 39 | NSString *seedPath = [[NSBundle mainBundle] pathForResource:@"RKSeedDatabase" 40 | ofType:@"sqlite"]; 41 | NSError *error; 42 | NSPersistentStore *persistentStore = 43 | [managedObjectStore addSQLitePersistentStoreAtPath:storePath 44 | fromSeedDatabaseAtPath:seedPath 45 | withConfiguration:nil 46 | options:nil 47 | error:&error]; 48 | NSAssert(persistentStore, @"Failed to add persistent store with error: %@", 49 | error); 50 | 51 | // Create the managed object contexts 52 | [managedObjectStore createManagedObjectContexts]; 53 | 54 | // Configure a managed object cache to ensure we do not create duplicate 55 | // objects 56 | managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] 57 | initWithManagedObjectContext:managedObjectStore 58 | .persistentStoreManagedObjectContext]; 59 | 60 | RKEntityMapping *articleListMapping = 61 | [RKEntityMapping mappingForEntityForName:@"ArticleList" 62 | inManagedObjectStore:managedObjectStore]; 63 | articleListMapping.identificationAttributes = @[ @"title" ]; 64 | [articleListMapping addAttributeMappingsFromDictionary:@{ 65 | @"title" : @"title", 66 | @"syndication_url" : @"url", 67 | @"description" : @"article_description" 68 | }]; 69 | 70 | RKEntityMapping *articleMapping = 71 | [RKEntityMapping mappingForEntityForName:@"Article" 72 | inManagedObjectStore:managedObjectStore]; 73 | articleMapping.identificationAttributes = @[ @"source_url" ]; 74 | [articleMapping addAttributeMappingsFromArray:@[ 75 | @"publish_date", 76 | @"source", 77 | @"source_url", 78 | @"summary", 79 | @"title", 80 | @"url" 81 | ]]; 82 | 83 | [articleListMapping 84 | addPropertyMapping:[RKRelationshipMapping 85 | relationshipMappingFromKeyPath:@"articles" 86 | toKeyPath:@"articles" 87 | withMapping:articleMapping]]; 88 | 89 | // Register article mapping with the provider 90 | RKResponseDescriptor *articleListResponseDescriptor = [RKResponseDescriptor 91 | responseDescriptorWithMapping:articleListMapping 92 | method:RKRequestMethodGET 93 | pathPattern:@"/v1/categories/:id/articles.json" 94 | keyPath:nil 95 | statusCodes:RKStatusCodeIndexSetForClass( 96 | RKStatusCodeClassSuccessful)]; 97 | [objectManager addResponseDescriptor:articleListResponseDescriptor]; 98 | 99 | // Enable Activity Indicator Spinner 100 | [AFNetworkActivityIndicatorManager sharedManager].enabled = YES; 101 | 102 | return YES; 103 | } 104 | 105 | - (void)applicationWillResignActive:(UIApplication *)application { 106 | // Sent when the application is about to move from active to inactive state. 107 | // This can occur for certain types of temporary interruptions (such as an 108 | // incoming phone call or SMS message) or when the user quits the application 109 | // and it begins the transition to the background state. 110 | // Use this method to pause ongoing tasks, disable timers, and throttle down 111 | // OpenGL ES frame rates. Games should use this method to pause the game. 112 | } 113 | 114 | - (void)applicationDidEnterBackground:(UIApplication *)application { 115 | // Use this method to release shared resources, save user data, invalidate 116 | // timers, and store enough application state information to restore your 117 | // application to its current state in case it is terminated later. 118 | // If your application supports background execution, this method is called 119 | // instead of applicationWillTerminate: when the user quits. 120 | } 121 | 122 | - (void)applicationWillEnterForeground:(UIApplication *)application { 123 | // Called as part of the transition from the background to the inactive state; 124 | // here you can undo many of the changes made on entering the background. 125 | } 126 | 127 | - (void)applicationDidBecomeActive:(UIApplication *)application { 128 | // Restart any tasks that were paused (or not yet started) while the 129 | // application was inactive. If the application was previously in the 130 | // background, optionally refresh the user interface. 131 | } 132 | 133 | - (void)applicationWillTerminate:(UIApplication *)application { 134 | // Called when the application is about to terminate. Save data if 135 | // appropriate. See also applicationDidEnterBackground:. 136 | } 137 | 138 | @end 139 | -------------------------------------------------------------------------------- /Articles/Article.h: -------------------------------------------------------------------------------- 1 | // 2 | // Article.h 3 | // Articles 4 | // 5 | // Created by Marcin on 03.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface Article : NSManagedObject 14 | 15 | @property (nonatomic, retain) NSDate * publish_date; 16 | @property (nonatomic, retain) NSString * source; 17 | @property (nonatomic, retain) NSString * source_url; 18 | @property (nonatomic, retain) NSString * summary; 19 | @property (nonatomic, retain) NSString * title; 20 | @property (nonatomic, retain) NSString * url; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Articles/Article.m: -------------------------------------------------------------------------------- 1 | // 2 | // Article.m 3 | // Articles 4 | // 5 | // Created by Marcin on 03.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import "Article.h" 10 | 11 | 12 | @implementation Article 13 | 14 | @dynamic publish_date; 15 | @dynamic source; 16 | @dynamic source_url; 17 | @dynamic summary; 18 | @dynamic title; 19 | @dynamic url; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Articles/ArticleList.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArticleList.h 3 | // Articles 4 | // 5 | // Created by Marcin on 03.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class Article; 13 | 14 | @interface ArticleList : NSManagedObject 15 | 16 | @property (nonatomic, retain) NSString * article_description; 17 | @property (nonatomic, retain) NSString * title; 18 | @property (nonatomic, retain) NSString * url; 19 | @property (nonatomic, retain) NSSet *articles; 20 | 21 | @end 22 | 23 | @interface ArticleList (CoreDataGeneratedAccessors) 24 | 25 | - (void)addArticlesObject:(Article *)value; 26 | - (void)removeArticlesObject:(Article *)value; 27 | - (void)addArticles:(NSSet *)values; 28 | - (void)removeArticles:(NSSet *)values; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Articles/ArticleList.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArticleList.m 3 | // Articles 4 | // 5 | // Created by Marcin on 03.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import "ArticleList.h" 10 | #import "Article.h" 11 | 12 | 13 | @implementation ArticleList 14 | 15 | @dynamic article_description; 16 | @dynamic title; 17 | @dynamic url; 18 | @dynamic articles; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Articles/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Articles/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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 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 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /Articles/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Articles/DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.h 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailViewController : UIViewController 12 | 13 | @property (strong, nonatomic) id detailItem; 14 | @property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel; 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Articles/DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.m 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import "DetailViewController.h" 10 | 11 | @interface DetailViewController () 12 | 13 | @end 14 | 15 | @implementation DetailViewController 16 | 17 | #pragma mark - Managing the detail item 18 | 19 | - (void)setDetailItem:(id)newDetailItem { 20 | if (_detailItem != newDetailItem) { 21 | _detailItem = newDetailItem; 22 | 23 | // Update the view. 24 | [self configureView]; 25 | } 26 | } 27 | 28 | - (void)configureView { 29 | // Update the user interface for the detail item. 30 | if (self.detailItem) { 31 | self.detailDescriptionLabel.text = [self.detailItem description]; 32 | } 33 | } 34 | 35 | - (void)viewDidLoad { 36 | [super viewDidLoad]; 37 | // Do any additional setup after loading the view, typically from a nib. 38 | [self configureView]; 39 | } 40 | 41 | - (void)didReceiveMemoryWarning { 42 | [super didReceiveMemoryWarning]; 43 | // Dispose of any resources that can be recreated. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Articles/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Articles/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.bonzoq.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeRight 47 | UIInterfaceOrientationLandscapeLeft 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Articles/MasterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MasterViewController.h 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MasterViewController : UITableViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Articles/MasterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MasterViewController.m 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import "MasterViewController.h" 10 | #import "DetailViewController.h" 11 | 12 | #import 13 | #import 14 | 15 | #import "Article.h" 16 | #import "ArticleList.h" 17 | 18 | @interface MasterViewController () 19 | 20 | @property NSArray *articles; 21 | 22 | @end 23 | 24 | @implementation MasterViewController 25 | 26 | - (void)awakeFromNib { 27 | [super awakeFromNib]; 28 | } 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | 33 | 34 | [self requestData]; 35 | } 36 | 37 | - (void)didReceiveMemoryWarning { 38 | [super didReceiveMemoryWarning]; 39 | // Dispose of any resources that can be recreated. 40 | } 41 | 42 | 43 | #pragma mark - Segues 44 | 45 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 46 | if ([[segue identifier] isEqualToString:@"showDetail"]) { 47 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 48 | Article *article = self.articles[indexPath.row]; 49 | [[segue destinationViewController] setDetailItem:article.summary]; 50 | } 51 | } 52 | 53 | #pragma mark - Table View 54 | 55 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 56 | return 1; 57 | } 58 | 59 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 60 | return [self.articles count]; 61 | } 62 | 63 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 64 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 65 | 66 | Article *article = self.articles[indexPath.row]; 67 | cell.textLabel.text = article.title; 68 | return cell; 69 | } 70 | 71 | 72 | #pragma mark - RESTKit 73 | 74 | - (void)requestData { 75 | NSString *requestPath = @"/v1/categories/16/articles.json"; 76 | 77 | [[RKObjectManager sharedManager] 78 | getObjectsAtPath:requestPath 79 | parameters:nil 80 | success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { 81 | 82 | //articles have been saved in core data by now 83 | 84 | [self fetchArticlesFromContext]; 85 | 86 | } 87 | failure: ^(RKObjectRequestOperation *operation, NSError *error) { 88 | RKLogError(@"Load failed with error: %@", error); 89 | } 90 | ]; 91 | } 92 | 93 | - (void)fetchArticlesFromContext { 94 | 95 | NSManagedObjectContext *context = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext; 96 | NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"ArticleList"]; 97 | 98 | NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]; 99 | fetchRequest.sortDescriptors = @[descriptor]; 100 | 101 | NSError *error = nil; 102 | NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; 103 | 104 | ArticleList *articleList = [fetchedObjects firstObject]; 105 | 106 | self.articles = [articleList.articles allObjects]; 107 | 108 | [self.tableView reloadData]; 109 | 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /Articles/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Articles 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. 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 | -------------------------------------------------------------------------------- /ArticlesTests/ArticlesTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArticlesTests.m 3 | // ArticlesTests 4 | // 5 | // Created by Marcin on 02.02.2015. 6 | // Copyright (c) 2015 Marcin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ArticlesTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation ArticlesTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ArticlesTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.bonzoq.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | pod 'RestKit' -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (1.3.4) 3 | - ISO8601DateFormatterValueTransformer (0.6.0): 4 | - RKValueTransformers (~> 1.1.0) 5 | - RestKit (0.24.0): 6 | - RestKit/Core (= 0.24.0) 7 | - RestKit/Core (0.24.0): 8 | - RestKit/CoreData 9 | - RestKit/Network 10 | - RestKit/ObjectMapping 11 | - RestKit/CoreData (0.24.0): 12 | - RestKit/ObjectMapping 13 | - RestKit/Network (0.24.0): 14 | - AFNetworking (~> 1.3.0) 15 | - RestKit/ObjectMapping 16 | - RestKit/Support 17 | - SOCKit 18 | - RestKit/ObjectMapping (0.24.0): 19 | - ISO8601DateFormatterValueTransformer (~> 0.6.0) 20 | - RestKit/Support 21 | - RKValueTransformers (~> 1.1.0) 22 | - RestKit/Support (0.24.0): 23 | - TransitionKit (= 2.1.0) 24 | - RKValueTransformers (1.1.1) 25 | - SOCKit (1.1) 26 | - TransitionKit (2.1.0) 27 | 28 | DEPENDENCIES: 29 | - RestKit 30 | 31 | SPEC CHECKSUMS: 32 | AFNetworking: 80c4e0652b08eb34e25b9c0ff3c82556fe5967b4 33 | ISO8601DateFormatterValueTransformer: a705384ea6531255258e25b6480ba1180db703a0 34 | RestKit: 8e301e50e1d25ce427215539f4fd72463f4a2a58 35 | RKValueTransformers: 67b4ea3eb6a1c1a0b8c3c37eb4e4c05e4febeba2 36 | SOCKit: d8d0dd3688ae1026c12367570da8fa8e1a6980fb 37 | TransitionKit: 6a6f3ddda38ae758778aa889dcb930e4f8d64edc 38 | 39 | COCOAPODS: 0.35.0 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RESTKitTutorial 2 | Final project from "RESTKit Tutorial: how to fetch data from a RESTful API into Core Data." 3 | 4 | https://medium.com/ios-os-x-development/restkit-tutorial-how-to-fetch-data-from-an-api-into-core-data-9326af750e10 5 | 6 | ##Installation 7 | 8 | Don't forget to install pods. 9 | 10 | This app requires CocoaPods dependency manager. It automates and simplifies the process of using 3rd-party libraries. If you don't have it yet, you can get it by typing the following in your console: 11 | 12 | ``` sh 13 | $ sudo gem install cocoapods 14 | ``` 15 | 16 | With CocoaPods up and running go to the application folder and install dependencies: 17 | 18 | ``` sh 19 | $ cd RESTKitTutorial 20 | $ pod install 21 | ``` 22 | Use `Articles.xcworkspace` to open the project. 23 | --------------------------------------------------------------------------------