├── .gitignore ├── README.md └── WordPress-API ├── WordPress-API.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── WordPress-API ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── DetailViewController.swift ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── PostListViewController.swift ├── PostTableViewCell.swift ├── String+html.swift └── WordPressWebServices.swift └── WordPress-APITests ├── Info.plist └── WordPress_APITests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | WordPress-API.xccheckout 2 | notes-pm-wordpress-API.txt 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WordPress-API-Demo 2 | 3 | This project was originaly written in Swift 1, for WordPress API version 1. 4 | It is now outdated. I'm rewritting it from scratch in Swift 3 for WordPress REST API version 2. 5 | 6 | The new project: 7 | [https://github.com/pierrem/WP](https://github.com/pierrem/WP) 8 | 9 | 10 | A iOS application written in Swift, that demonstrates the communication with WordPress. The code has been kept simple and minimalist. In particular, error conditions are not reported to the user! 11 | WordPress site URL is hardcoded. You can change it in WordPress Web Services.swift. 12 | 13 | The Wordpress API is available for any WordPress.com site as well as any self-hosted (WordPress.org) site connected via Jetpack : 14 | https://developer.wordpress.com/docs/api/getting-started/ 15 | 16 | May 2017 : This project is now outdated (originaly written in Swift 1). I have just fixed compilation error with XCode 8 / swift 3. I intend to rewrite it from scratch using Swift 3. 17 | 18 | 19 | 16 may 2016 : Fixed a problem with SplitView on iPhone. 20 | 21 | 28 jan 2016 : Droped categories, code simplification and bug fixes. 22 | 23 | 27 jan 2016 : NSAllowsArbitraryLoads to allow loading images in webView. 24 | 25 | 6 oct 2015 : XCode 7 & Swift 2. 26 | The code hasn't yet be reworked to use new Swift construction (guard for exemple) that will allow cleaner code. 27 | 28 | 9 May 2015 : + featured image in the post list table. 29 | 30 | WordPress REST API documentation: [https://developer.wordpress.com/docs/api](https://developer.wordpress.com/docs/api) 31 | 32 | © Pierre Marty 2015 33 | [http://www.alpeslog.com](http://www.alpeslog.com) 34 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8F0BB1B51A8BB2C6003F3C8B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0BB1B41A8BB2C6003F3C8B /* AppDelegate.swift */; }; 11 | 8F0BB1B91A8BB2C6003F3C8B /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0BB1B81A8BB2C6003F3C8B /* DetailViewController.swift */; }; 12 | 8F0BB1BC1A8BB2C6003F3C8B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8F0BB1BA1A8BB2C6003F3C8B /* Main.storyboard */; }; 13 | 8F0BB1BE1A8BB2C6003F3C8B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8F0BB1BD1A8BB2C6003F3C8B /* Images.xcassets */; }; 14 | 8F0BB1C11A8BB2C6003F3C8B /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8F0BB1BF1A8BB2C6003F3C8B /* LaunchScreen.xib */; }; 15 | 8F0BB1CD1A8BB2C6003F3C8B /* WordPress_APITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0BB1CC1A8BB2C6003F3C8B /* WordPress_APITests.swift */; }; 16 | 8F0BB1D71A8BB599003F3C8B /* WordPressWebServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0BB1D61A8BB599003F3C8B /* WordPressWebServices.swift */; }; 17 | 8F0BB1D91A8C0355003F3C8B /* PostListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0BB1D81A8C0355003F3C8B /* PostListViewController.swift */; }; 18 | 8F4CD9541C5BAB380043AE35 /* PostTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F4CD9531C5BAB380043AE35 /* PostTableViewCell.swift */; }; 19 | 8FDF60D91C5AB97B003FA96B /* String+html.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FDF60D81C5AB97B003FA96B /* String+html.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 8F0BB1C71A8BB2C6003F3C8B /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 8F0BB1A71A8BB2C6003F3C8B /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 8F0BB1AE1A8BB2C6003F3C8B; 28 | remoteInfo = "WordPress-API"; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 8F0BB1AF1A8BB2C6003F3C8B /* WordPress-API.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "WordPress-API.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 8F0BB1B31A8BB2C6003F3C8B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | 8F0BB1B41A8BB2C6003F3C8B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 36 | 8F0BB1B81A8BB2C6003F3C8B /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; }; 37 | 8F0BB1BB1A8BB2C6003F3C8B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 38 | 8F0BB1BD1A8BB2C6003F3C8B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 39 | 8F0BB1C01A8BB2C6003F3C8B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 40 | 8F0BB1C61A8BB2C6003F3C8B /* WordPress-APITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "WordPress-APITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 8F0BB1CB1A8BB2C6003F3C8B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 8F0BB1CC1A8BB2C6003F3C8B /* WordPress_APITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPress_APITests.swift; sourceTree = ""; }; 43 | 8F0BB1D61A8BB599003F3C8B /* WordPressWebServices.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WordPressWebServices.swift; sourceTree = ""; }; 44 | 8F0BB1D81A8C0355003F3C8B /* PostListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostListViewController.swift; sourceTree = ""; }; 45 | 8F4CD9531C5BAB380043AE35 /* PostTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostTableViewCell.swift; sourceTree = ""; }; 46 | 8F529AA41C5A72CB00C7966D /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 47 | 8FDF60D81C5AB97B003FA96B /* String+html.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+html.swift"; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 8F0BB1AC1A8BB2C6003F3C8B /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | 8F0BB1C31A8BB2C6003F3C8B /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 8F0BB1A61A8BB2C6003F3C8B = { 69 | isa = PBXGroup; 70 | children = ( 71 | 8F529AA41C5A72CB00C7966D /* README.md */, 72 | 8F0BB1B11A8BB2C6003F3C8B /* WordPress-API */, 73 | 8F0BB1C91A8BB2C6003F3C8B /* WordPress-APITests */, 74 | 8F0BB1B01A8BB2C6003F3C8B /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 8F0BB1B01A8BB2C6003F3C8B /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 8F0BB1AF1A8BB2C6003F3C8B /* WordPress-API.app */, 82 | 8F0BB1C61A8BB2C6003F3C8B /* WordPress-APITests.xctest */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | 8F0BB1B11A8BB2C6003F3C8B /* WordPress-API */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 8F0BB1B41A8BB2C6003F3C8B /* AppDelegate.swift */, 91 | 8F0BB1D81A8C0355003F3C8B /* PostListViewController.swift */, 92 | 8F4CD9531C5BAB380043AE35 /* PostTableViewCell.swift */, 93 | 8F0BB1B81A8BB2C6003F3C8B /* DetailViewController.swift */, 94 | 8F0BB1D61A8BB599003F3C8B /* WordPressWebServices.swift */, 95 | 8FDF60D81C5AB97B003FA96B /* String+html.swift */, 96 | 8F0BB1BA1A8BB2C6003F3C8B /* Main.storyboard */, 97 | 8F0BB1BD1A8BB2C6003F3C8B /* Images.xcassets */, 98 | 8F0BB1BF1A8BB2C6003F3C8B /* LaunchScreen.xib */, 99 | 8F0BB1B21A8BB2C6003F3C8B /* Supporting Files */, 100 | ); 101 | path = "WordPress-API"; 102 | sourceTree = ""; 103 | }; 104 | 8F0BB1B21A8BB2C6003F3C8B /* Supporting Files */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 8F0BB1B31A8BB2C6003F3C8B /* Info.plist */, 108 | ); 109 | name = "Supporting Files"; 110 | sourceTree = ""; 111 | }; 112 | 8F0BB1C91A8BB2C6003F3C8B /* WordPress-APITests */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 8F0BB1CC1A8BB2C6003F3C8B /* WordPress_APITests.swift */, 116 | 8F0BB1CA1A8BB2C6003F3C8B /* Supporting Files */, 117 | ); 118 | path = "WordPress-APITests"; 119 | sourceTree = ""; 120 | }; 121 | 8F0BB1CA1A8BB2C6003F3C8B /* Supporting Files */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 8F0BB1CB1A8BB2C6003F3C8B /* Info.plist */, 125 | ); 126 | name = "Supporting Files"; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | 8F0BB1AE1A8BB2C6003F3C8B /* WordPress-API */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 8F0BB1D01A8BB2C6003F3C8B /* Build configuration list for PBXNativeTarget "WordPress-API" */; 135 | buildPhases = ( 136 | 8F0BB1AB1A8BB2C6003F3C8B /* Sources */, 137 | 8F0BB1AC1A8BB2C6003F3C8B /* Frameworks */, 138 | 8F0BB1AD1A8BB2C6003F3C8B /* Resources */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | ); 144 | name = "WordPress-API"; 145 | productName = "WordPress-API"; 146 | productReference = 8F0BB1AF1A8BB2C6003F3C8B /* WordPress-API.app */; 147 | productType = "com.apple.product-type.application"; 148 | }; 149 | 8F0BB1C51A8BB2C6003F3C8B /* WordPress-APITests */ = { 150 | isa = PBXNativeTarget; 151 | buildConfigurationList = 8F0BB1D31A8BB2C6003F3C8B /* Build configuration list for PBXNativeTarget "WordPress-APITests" */; 152 | buildPhases = ( 153 | 8F0BB1C21A8BB2C6003F3C8B /* Sources */, 154 | 8F0BB1C31A8BB2C6003F3C8B /* Frameworks */, 155 | 8F0BB1C41A8BB2C6003F3C8B /* Resources */, 156 | ); 157 | buildRules = ( 158 | ); 159 | dependencies = ( 160 | 8F0BB1C81A8BB2C6003F3C8B /* PBXTargetDependency */, 161 | ); 162 | name = "WordPress-APITests"; 163 | productName = "WordPress-APITests"; 164 | productReference = 8F0BB1C61A8BB2C6003F3C8B /* WordPress-APITests.xctest */; 165 | productType = "com.apple.product-type.bundle.unit-test"; 166 | }; 167 | /* End PBXNativeTarget section */ 168 | 169 | /* Begin PBXProject section */ 170 | 8F0BB1A71A8BB2C6003F3C8B /* Project object */ = { 171 | isa = PBXProject; 172 | attributes = { 173 | LastSwiftMigration = 0700; 174 | LastSwiftUpdateCheck = 0700; 175 | LastUpgradeCheck = 0700; 176 | ORGANIZATIONNAME = "Pierre Marty"; 177 | TargetAttributes = { 178 | 8F0BB1AE1A8BB2C6003F3C8B = { 179 | CreatedOnToolsVersion = 6.3; 180 | DevelopmentTeam = 977VW2JR38; 181 | LastSwiftMigration = 0820; 182 | }; 183 | 8F0BB1C51A8BB2C6003F3C8B = { 184 | CreatedOnToolsVersion = 6.3; 185 | LastSwiftMigration = 0820; 186 | TestTargetID = 8F0BB1AE1A8BB2C6003F3C8B; 187 | }; 188 | }; 189 | }; 190 | buildConfigurationList = 8F0BB1AA1A8BB2C6003F3C8B /* Build configuration list for PBXProject "WordPress-API" */; 191 | compatibilityVersion = "Xcode 3.2"; 192 | developmentRegion = English; 193 | hasScannedForEncodings = 0; 194 | knownRegions = ( 195 | en, 196 | Base, 197 | ); 198 | mainGroup = 8F0BB1A61A8BB2C6003F3C8B; 199 | productRefGroup = 8F0BB1B01A8BB2C6003F3C8B /* Products */; 200 | projectDirPath = ""; 201 | projectRoot = ""; 202 | targets = ( 203 | 8F0BB1AE1A8BB2C6003F3C8B /* WordPress-API */, 204 | 8F0BB1C51A8BB2C6003F3C8B /* WordPress-APITests */, 205 | ); 206 | }; 207 | /* End PBXProject section */ 208 | 209 | /* Begin PBXResourcesBuildPhase section */ 210 | 8F0BB1AD1A8BB2C6003F3C8B /* Resources */ = { 211 | isa = PBXResourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | 8F0BB1BC1A8BB2C6003F3C8B /* Main.storyboard in Resources */, 215 | 8F0BB1C11A8BB2C6003F3C8B /* LaunchScreen.xib in Resources */, 216 | 8F0BB1BE1A8BB2C6003F3C8B /* Images.xcassets in Resources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | 8F0BB1C41A8BB2C6003F3C8B /* Resources */ = { 221 | isa = PBXResourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXResourcesBuildPhase section */ 228 | 229 | /* Begin PBXSourcesBuildPhase section */ 230 | 8F0BB1AB1A8BB2C6003F3C8B /* Sources */ = { 231 | isa = PBXSourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | 8F0BB1D71A8BB599003F3C8B /* WordPressWebServices.swift in Sources */, 235 | 8F0BB1D91A8C0355003F3C8B /* PostListViewController.swift in Sources */, 236 | 8F0BB1B91A8BB2C6003F3C8B /* DetailViewController.swift in Sources */, 237 | 8F0BB1B51A8BB2C6003F3C8B /* AppDelegate.swift in Sources */, 238 | 8FDF60D91C5AB97B003FA96B /* String+html.swift in Sources */, 239 | 8F4CD9541C5BAB380043AE35 /* PostTableViewCell.swift in Sources */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | 8F0BB1C21A8BB2C6003F3C8B /* Sources */ = { 244 | isa = PBXSourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | 8F0BB1CD1A8BB2C6003F3C8B /* WordPress_APITests.swift in Sources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXSourcesBuildPhase section */ 252 | 253 | /* Begin PBXTargetDependency section */ 254 | 8F0BB1C81A8BB2C6003F3C8B /* PBXTargetDependency */ = { 255 | isa = PBXTargetDependency; 256 | target = 8F0BB1AE1A8BB2C6003F3C8B /* WordPress-API */; 257 | targetProxy = 8F0BB1C71A8BB2C6003F3C8B /* PBXContainerItemProxy */; 258 | }; 259 | /* End PBXTargetDependency section */ 260 | 261 | /* Begin PBXVariantGroup section */ 262 | 8F0BB1BA1A8BB2C6003F3C8B /* Main.storyboard */ = { 263 | isa = PBXVariantGroup; 264 | children = ( 265 | 8F0BB1BB1A8BB2C6003F3C8B /* Base */, 266 | ); 267 | name = Main.storyboard; 268 | sourceTree = ""; 269 | }; 270 | 8F0BB1BF1A8BB2C6003F3C8B /* LaunchScreen.xib */ = { 271 | isa = PBXVariantGroup; 272 | children = ( 273 | 8F0BB1C01A8BB2C6003F3C8B /* Base */, 274 | ); 275 | name = LaunchScreen.xib; 276 | sourceTree = ""; 277 | }; 278 | /* End PBXVariantGroup section */ 279 | 280 | /* Begin XCBuildConfiguration section */ 281 | 8F0BB1CE1A8BB2C6003F3C8B /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ALWAYS_SEARCH_USER_PATHS = NO; 285 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 286 | CLANG_CXX_LIBRARY = "libc++"; 287 | CLANG_ENABLE_MODULES = YES; 288 | CLANG_ENABLE_OBJC_ARC = YES; 289 | CLANG_WARN_BOOL_CONVERSION = YES; 290 | CLANG_WARN_CONSTANT_CONVERSION = YES; 291 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 292 | CLANG_WARN_EMPTY_BODY = YES; 293 | CLANG_WARN_ENUM_CONVERSION = YES; 294 | CLANG_WARN_INT_CONVERSION = YES; 295 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 296 | CLANG_WARN_UNREACHABLE_CODE = YES; 297 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 298 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 299 | COPY_PHASE_STRIP = NO; 300 | DEBUG_INFORMATION_FORMAT = dwarf; 301 | ENABLE_STRICT_OBJC_MSGSEND = YES; 302 | ENABLE_TESTABILITY = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu99; 304 | GCC_DYNAMIC_NO_PIC = NO; 305 | GCC_OPTIMIZATION_LEVEL = 0; 306 | GCC_PREPROCESSOR_DEFINITIONS = ( 307 | "DEBUG=1", 308 | "$(inherited)", 309 | ); 310 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 313 | GCC_WARN_UNDECLARED_SELECTOR = YES; 314 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 315 | GCC_WARN_UNUSED_FUNCTION = YES; 316 | GCC_WARN_UNUSED_VARIABLE = YES; 317 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 318 | MTL_ENABLE_DEBUG_INFO = YES; 319 | ONLY_ACTIVE_ARCH = YES; 320 | SDKROOT = iphoneos; 321 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 322 | SWIFT_VERSION = 3.0; 323 | TARGETED_DEVICE_FAMILY = "1,2"; 324 | }; 325 | name = Debug; 326 | }; 327 | 8F0BB1CF1A8BB2C6003F3C8B /* Release */ = { 328 | isa = XCBuildConfiguration; 329 | buildSettings = { 330 | ALWAYS_SEARCH_USER_PATHS = NO; 331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 332 | CLANG_CXX_LIBRARY = "libc++"; 333 | CLANG_ENABLE_MODULES = YES; 334 | CLANG_ENABLE_OBJC_ARC = YES; 335 | CLANG_WARN_BOOL_CONVERSION = YES; 336 | CLANG_WARN_CONSTANT_CONVERSION = YES; 337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 338 | CLANG_WARN_EMPTY_BODY = YES; 339 | CLANG_WARN_ENUM_CONVERSION = YES; 340 | CLANG_WARN_INT_CONVERSION = YES; 341 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 342 | CLANG_WARN_UNREACHABLE_CODE = YES; 343 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 344 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 345 | COPY_PHASE_STRIP = NO; 346 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 347 | ENABLE_NS_ASSERTIONS = NO; 348 | ENABLE_STRICT_OBJC_MSGSEND = YES; 349 | GCC_C_LANGUAGE_STANDARD = gnu99; 350 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 351 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 352 | GCC_WARN_UNDECLARED_SELECTOR = YES; 353 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 354 | GCC_WARN_UNUSED_FUNCTION = YES; 355 | GCC_WARN_UNUSED_VARIABLE = YES; 356 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 357 | MTL_ENABLE_DEBUG_INFO = NO; 358 | SDKROOT = iphoneos; 359 | SWIFT_VERSION = 3.0; 360 | TARGETED_DEVICE_FAMILY = "1,2"; 361 | VALIDATE_PRODUCT = YES; 362 | }; 363 | name = Release; 364 | }; 365 | 8F0BB1D11A8BB2C6003F3C8B /* Debug */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 369 | DEVELOPMENT_TEAM = 977VW2JR38; 370 | INFOPLIST_FILE = "WordPress-API/Info.plist"; 371 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 372 | PRODUCT_BUNDLE_IDENTIFIER = "alpeslog.com.$(PRODUCT_NAME:rfc1034identifier)"; 373 | PRODUCT_NAME = "$(TARGET_NAME)"; 374 | SWIFT_VERSION = 3.0; 375 | }; 376 | name = Debug; 377 | }; 378 | 8F0BB1D21A8BB2C6003F3C8B /* Release */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 382 | DEVELOPMENT_TEAM = 977VW2JR38; 383 | INFOPLIST_FILE = "WordPress-API/Info.plist"; 384 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 385 | PRODUCT_BUNDLE_IDENTIFIER = "alpeslog.com.$(PRODUCT_NAME:rfc1034identifier)"; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | SWIFT_VERSION = 3.0; 388 | }; 389 | name = Release; 390 | }; 391 | 8F0BB1D41A8BB2C6003F3C8B /* Debug */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | BUNDLE_LOADER = "$(TEST_HOST)"; 395 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 396 | GCC_PREPROCESSOR_DEFINITIONS = ( 397 | "DEBUG=1", 398 | "$(inherited)", 399 | ); 400 | INFOPLIST_FILE = "WordPress-APITests/Info.plist"; 401 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 402 | PRODUCT_BUNDLE_IDENTIFIER = "alpeslog.com.$(PRODUCT_NAME:rfc1034identifier)"; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | SWIFT_VERSION = 3.0; 405 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WordPress-API.app/WordPress-API"; 406 | }; 407 | name = Debug; 408 | }; 409 | 8F0BB1D51A8BB2C6003F3C8B /* Release */ = { 410 | isa = XCBuildConfiguration; 411 | buildSettings = { 412 | BUNDLE_LOADER = "$(TEST_HOST)"; 413 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 414 | INFOPLIST_FILE = "WordPress-APITests/Info.plist"; 415 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 416 | PRODUCT_BUNDLE_IDENTIFIER = "alpeslog.com.$(PRODUCT_NAME:rfc1034identifier)"; 417 | PRODUCT_NAME = "$(TARGET_NAME)"; 418 | SWIFT_VERSION = 3.0; 419 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WordPress-API.app/WordPress-API"; 420 | }; 421 | name = Release; 422 | }; 423 | /* End XCBuildConfiguration section */ 424 | 425 | /* Begin XCConfigurationList section */ 426 | 8F0BB1AA1A8BB2C6003F3C8B /* Build configuration list for PBXProject "WordPress-API" */ = { 427 | isa = XCConfigurationList; 428 | buildConfigurations = ( 429 | 8F0BB1CE1A8BB2C6003F3C8B /* Debug */, 430 | 8F0BB1CF1A8BB2C6003F3C8B /* Release */, 431 | ); 432 | defaultConfigurationIsVisible = 0; 433 | defaultConfigurationName = Release; 434 | }; 435 | 8F0BB1D01A8BB2C6003F3C8B /* Build configuration list for PBXNativeTarget "WordPress-API" */ = { 436 | isa = XCConfigurationList; 437 | buildConfigurations = ( 438 | 8F0BB1D11A8BB2C6003F3C8B /* Debug */, 439 | 8F0BB1D21A8BB2C6003F3C8B /* Release */, 440 | ); 441 | defaultConfigurationIsVisible = 0; 442 | defaultConfigurationName = Release; 443 | }; 444 | 8F0BB1D31A8BB2C6003F3C8B /* Build configuration list for PBXNativeTarget "WordPress-APITests" */ = { 445 | isa = XCConfigurationList; 446 | buildConfigurations = ( 447 | 8F0BB1D41A8BB2C6003F3C8B /* Debug */, 448 | 8F0BB1D51A8BB2C6003F3C8B /* Release */, 449 | ); 450 | defaultConfigurationIsVisible = 0; 451 | defaultConfigurationName = Release; 452 | }; 453 | /* End XCConfigurationList section */ 454 | }; 455 | rootObject = 8F0BB1A71A8BB2C6003F3C8B /* Project object */; 456 | } 457 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // WordPress-API 4 | // 5 | // Created by Pierre Marty on 11/02/2015. 6 | // Copyright (c) 2015 Pierre Marty. All rights reserved. 7 | // 8 | 9 | 10 | import UIKit 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | let splitViewController = self.window!.rootViewController as! UISplitViewController 20 | let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController 21 | navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem 22 | splitViewController.delegate = self 23 | return true 24 | } 25 | 26 | func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { 27 | guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false } 28 | guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false } 29 | if topAsDetailController.detailItem == nil { 30 | // Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded. 31 | return true 32 | } 33 | return false 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/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 | 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 | 113 | 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 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/DetailViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.swift 3 | // WordPress-API 4 | // 5 | // Created by Pierre Marty on 11/02/2015. 6 | // Copyright (c) 2015 Pierre Marty. All rights reserved. 7 | // 8 | 9 | 10 | import UIKit 11 | 12 | class DetailViewController: UIViewController { 13 | 14 | @IBOutlet weak var webView: UIWebView! 15 | 16 | var postContent:Dictionary? = [:] 17 | 18 | var detailItem: Any? { 19 | didSet { 20 | self.updatePost() 21 | } 22 | } 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | // add the displayModeButtonItem in the navigation bar of the detail view controller (visible on iPad in portrait mode) 27 | self.navigationController!.topViewController!.navigationItem.leftBarButtonItem = splitViewController!.displayModeButtonItem 28 | } 29 | 30 | 31 | func updatePost() { 32 | if let postDesc = self.detailItem as? Dictionary, let identifier = postDesc["ID"] as? Int { 33 | WordPressWebServices.sharedInstance.postByIdentifier(identifier, completionHandler: { (postContent, error) -> Void in 34 | if postContent != nil { 35 | self.postContent = postContent 36 | DispatchQueue.main.async(execute: { // access to UI in the main thread 37 | self.updateWebView() 38 | }) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | func updateWebView() { 45 | if let contentString = self.postContent!["content"] as? String { 46 | webView.loadHTMLString(contentString, baseURL: nil) 47 | } 48 | if let titleString = self.postContent!["title"] as? String { 49 | self.navigationItem.title = String(htmlEncodedString: titleString); 50 | } 51 | 52 | } 53 | 54 | } 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/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 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UIStatusBarTintParameters 39 | 40 | UINavigationBar 41 | 42 | Style 43 | UIBarStyleDefault 44 | Translucent 45 | 46 | 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UISupportedInterfaceOrientations~ipad 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationPortraitUpsideDown 58 | UIInterfaceOrientationLandscapeLeft 59 | UIInterfaceOrientationLandscapeRight 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/PostListViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostListViewController.swift 3 | // WordPress-API 4 | // 5 | // Created by Pierre Marty on 11/02/2015. 6 | // Copyright (c) 2015 Pierre Marty. All rights reserved. 7 | // 8 | 9 | // 10 | // This controller is in charge of the list of posts 11 | // 12 | 13 | 14 | import UIKit 15 | 16 | class PostListViewController: UITableViewController { 17 | 18 | var category = Dictionary() 19 | var posts = [Dictionary]() 20 | 21 | override func awakeFromNib() { 22 | super.awakeFromNib() 23 | if UIDevice.current.userInterfaceIdiom == .pad { 24 | self.clearsSelectionOnViewWillAppear = false 25 | self.preferredContentSize = CGSize(width: 320.0, height: 600.0) 26 | } 27 | } 28 | 29 | override func viewDidLoad() { 30 | super.viewDidLoad() 31 | self.updatePostList() 32 | } 33 | 34 | func updatePostList() { 35 | WordPressWebServices.sharedInstance.lastPosts(page:1, number: 100, completionHandler: { (posts, error) -> Void in 36 | if posts != nil { 37 | self.posts = posts! 38 | DispatchQueue.main.async(execute: { // access to UI in the main thread only ! 39 | self.tableView.reloadData() 40 | }) 41 | } 42 | }) 43 | } 44 | 45 | 46 | // MARK: - Segues 47 | 48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 49 | if segue.identifier == "showDetail" { 50 | if let indexPath = self.tableView.indexPathForSelectedRow { 51 | let post = posts[indexPath.row] 52 | let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController 53 | controller.detailItem = post 54 | controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem 55 | controller.navigationItem.leftItemsSupplementBackButton = true 56 | } 57 | } 58 | } 59 | 60 | 61 | // MARK: - Table View 62 | 63 | override func numberOfSections(in tableView: UITableView) -> Int { 64 | return 1 65 | } 66 | 67 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 68 | return posts.count 69 | } 70 | 71 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 72 | let cell = tableView.dequeueReusableCell(withIdentifier: "Post", for: indexPath) as! PostTableViewCell 73 | let post = posts[indexPath.row] 74 | cell.configureWithPostDictionary(post); 75 | return cell 76 | } 77 | 78 | } 79 | 80 | 81 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/PostTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostTableViewCell.swift 3 | // WordPress-API 4 | // 5 | // Created by Pierre Marty on 29/01/2016. 6 | // Copyright © 2016 Pierre Marty. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PostTableViewCell: UITableViewCell { 12 | 13 | @IBOutlet weak var titleLabel: UILabel! 14 | @IBOutlet weak var dateLabel: UILabel! 15 | @IBOutlet weak var featuredImageView: UIImageView! 16 | 17 | var postIdentifier:Int = 0 18 | var imageRequestedForIdentifier:Int = 0 19 | 20 | func configureWithPostDictionary (_ post:Dictionary) { 21 | 22 | let title = post["title"] as? String 23 | self.titleLabel!.text = String(htmlEncodedString: title!) 24 | 25 | self.dateLabel!.text = nil; 26 | 27 | if let dateStringFull = post["date"] as? String { 28 | // date is in the format "2016-01-29T01:45:33+02:00", 29 | let dateString = dateStringFull.substring(to: dateStringFull.characters.index(dateStringFull.startIndex, offsetBy: 10)) // keep only the date part 30 | 31 | let parsingDateFormatter = DateFormatter() // TODO: a static var 32 | parsingDateFormatter.dateFormat = "yyyy-MM-dd" 33 | let date = parsingDateFormatter.date(from: dateString) 34 | 35 | let printingDateFormatter = DateFormatter() // TODO: a static var 36 | printingDateFormatter.dateStyle = .long 37 | printingDateFormatter.timeStyle = .none 38 | 39 | self.dateLabel!.text = printingDateFormatter.string(from: date!) 40 | } 41 | 42 | self.featuredImageView!.image = nil; 43 | if let idf = post["ID"] as? Int { 44 | postIdentifier = idf 45 | } 46 | 47 | if let url = post["featured_image"] as? String { // there is a link to an image 48 | if url != "" { 49 | imageRequestedForIdentifier = postIdentifier 50 | WordPressWebServices.sharedInstance.loadImage (url, completionHandler: {(image, error) -> Void in 51 | DispatchQueue.main.async(execute: { 52 | // test if the cell has been recycled since we request the image ! 53 | if self.postIdentifier == self.imageRequestedForIdentifier { 54 | self.featuredImageView!.image = image; 55 | self.setNeedsLayout() 56 | } 57 | else { 58 | print("postIdentifier: \(self.postIdentifier) different from imageRequestedForIdentifier: \(self.imageRequestedForIdentifier)") 59 | } 60 | }) 61 | }) 62 | } 63 | } 64 | 65 | } 66 | 67 | } 68 | 69 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/String+html.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+html.swift 3 | // WordPress-API 4 | // 5 | // Created by Pierre Marty on 28/01/2016. 6 | // Copyright © 2016 Pierre Marty. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // http://stackoverflow.com/questions/25607247/how-do-i-decode-html-entities-in-swift 12 | 13 | extension String { 14 | init?(htmlEncodedString: String) { 15 | let encodedData = htmlEncodedString.data(using: String.Encoding.utf8)! 16 | let attributedOptions : [String: Any] = [ 17 | NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, 18 | NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue 19 | ] 20 | 21 | var attributedString:NSAttributedString? 22 | 23 | do { 24 | attributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil) 25 | 26 | // public init(data: Data, options: [String : Any] = [:], documentAttributes dict: AutoreleasingUnsafeMutablePointer?) throws 27 | // attributedString = try NSAttributedString(data: encodedData, options: [:], documentAttributes: nil) 28 | } catch { 29 | print(error) 30 | } 31 | 32 | self.init(attributedString!.string) 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-API/WordPressWebServices.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WordPressWebServices.swift 3 | // WordPress-API 4 | // 5 | // Created by Pierre Marty on 11/02/2015. 6 | // Copyright (c) 2015 Pierre Marty. All rights reserved. 7 | // 8 | 9 | // WordPress REST API documentation: https://developer.wordpress.com/docs/api/ 10 | 11 | 12 | import Foundation 13 | import UIKit 14 | 15 | class WordPressWebServices { 16 | 17 | // your site url here ! 18 | static let siteURL = "https://public-api.wordpress.com/rest/v1.1/sites/developer.wordpress.com" 19 | 20 | static let sharedInstance = WordPressWebServices(url:siteURL) // singleton instanciation 21 | 22 | fileprivate var baseURL:String?; 23 | 24 | convenience init(url: String) { 25 | self.init() 26 | self.baseURL = url 27 | } 28 | 29 | func postByIdentifier (_ identifier:Int, completionHandler:@escaping (Dictionary?, NSError?) -> Void) { 30 | let requestURL = baseURL! + "/posts/\(identifier)?fields=date,title,content" 31 | let url = URL(string: requestURL)! 32 | let urlSession = URLSession.shared 33 | 34 | let dataTask = urlSession.dataTask(with: url, completionHandler: { (data, response, error) -> Void in 35 | if error != nil { 36 | completionHandler(nil, error as NSError?); 37 | return; 38 | } 39 | var jsonError: NSError? 40 | var jsonResult:Any? 41 | do { 42 | jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) 43 | } catch let error as NSError { 44 | jsonError = error 45 | jsonResult = nil 46 | } catch { 47 | fatalError() 48 | } 49 | completionHandler(jsonResult as? Dictionary, jsonError); 50 | }) 51 | 52 | dataTask.resume() 53 | } 54 | 55 | // page parameter is one based [1..[ 56 | func lastPosts (page:Int, number:Int, completionHandler:@escaping (Array>?, NSError?) -> Void) { 57 | let requestURL = baseURL! + "/posts/?page=\(page)&number=\(number)&fields=ID,title,date,featured_image" 58 | let url = URL(string: requestURL)! 59 | let urlSession = URLSession.shared 60 | 61 | let dataTask = urlSession.dataTask(with: url, completionHandler: { (data, response, error) -> Void in 62 | if error != nil { 63 | completionHandler(nil, error as NSError?); 64 | return; 65 | } 66 | var jsonError: NSError? 67 | var jsonResult:Any? 68 | do { 69 | jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) 70 | } catch let error as NSError { 71 | jsonError = error 72 | jsonResult = nil 73 | } catch { 74 | fatalError() 75 | } 76 | var articles:Array> = [] 77 | 78 | if let resultDictionary = jsonResult as? Dictionary, 79 | let posts = resultDictionary["posts"] as? [Dictionary] { 80 | for post in posts { 81 | if let _ = post["ID"] as? Int, 82 | let _ = post["title"] as? String { 83 | articles.append(post) 84 | } 85 | } 86 | } 87 | completionHandler(articles, jsonError); 88 | }) 89 | 90 | dataTask.resume() 91 | } 92 | 93 | 94 | func loadImage (_ url: String, completionHandler:@escaping (UIImage?, NSError?) -> Void) { 95 | let url = URL(string: url)! 96 | let urlSession = URLSession.shared 97 | 98 | let dataTask = urlSession.dataTask(with: url, completionHandler: { (data, response, error) -> Void in 99 | if error == nil { 100 | let image = UIImage(data:data!); 101 | completionHandler(image, nil); 102 | } 103 | else { 104 | completionHandler(nil, error as NSError?); 105 | } 106 | }) 107 | 108 | dataTask.resume() 109 | } 110 | 111 | } 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-APITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /WordPress-API/WordPress-APITests/WordPress_APITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WordPress_APITests.swift 3 | // WordPress-APITests 4 | // 5 | // Created by Pierre Marty on 11/02/2015. 6 | // Copyright (c) 2015 Pierre Marty. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class WordPress_APITests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------