├── .gitignore ├── JokeClient-Swift.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── JokeClient-Swift.xccheckout │ └── xcuserdata │ │ ├── appdev.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── ruiyang.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── yangreal.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── appdev.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── JokeClient-Swift.xcscheme │ │ └── xcschememanagement.plist │ ├── ruiyang.xcuserdatad │ └── xcschemes │ │ ├── JokeClient-Swift.xcscheme │ │ └── xcschememanagement.plist │ └── yangreal.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── JokeClient-Swift.xcscheme │ └── xcschememanagement.plist ├── JokeClient-Swift ├── AppDelegate.swift ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ ├── 1136.png │ │ ├── 1242.png │ │ ├── 750.png │ │ ├── 960.png │ │ └── Contents.json ├── Info.plist ├── Utility │ ├── FileUtility.swift │ ├── NSDictionaryExt.swift │ ├── NSStringExt.swift │ ├── UIImageViewWebExt.swift │ ├── UIViewExt.swift │ └── YRHttpRequest.swift ├── View │ ├── YRCommnentsCell.swift │ ├── YRCommnentsCell.xib │ ├── YRImageZoomingView.swift │ ├── YRJokeCell.swift │ ├── YRJokeCell.xib │ ├── YRRefreshView.swift │ └── YRRefreshView.xib ├── ViewController │ ├── YRAboutViewController.swift │ ├── YRAboutViewController.xib │ ├── YRCommentsViewController.swift │ ├── YRImageViewController.swift │ ├── YRJokeTableViewController.swift │ └── YRMainViewController.swift ├── image │ ├── avatar.jpg │ └── me.jpeg └── screenshoot │ ├── 01.png │ ├── 02.png │ ├── 03.png │ └── 04.png ├── JokeClient-SwiftTests ├── Info.plist └── JokeClient_SwiftTests.swift ├── README.md └── screenshoot ├── 01.png ├── 02.png ├── 03.png └── 04.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | .DS_Store 10 | 11 | ## Various settings 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata 21 | 22 | ## Other 23 | *.xccheckout 24 | *.moved-aside 25 | *.xcuserstate 26 | *.xcscmblueprint 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | 32 | # CocoaPods 33 | # 34 | # We recommend against adding the Pods directory to your .gitignore. However 35 | # you should judge for yourself, the pros and cons are mentioned at: 36 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 37 | # 38 | # Pods/ 39 | 40 | # Carthage 41 | # 42 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 43 | # Carthage/Checkouts 44 | 45 | Carthage/Build 46 | 47 | # fastlane 48 | # 49 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 50 | # screenshots whenever they are needed. 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6E53E908194352320021598F /* avatar.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E906194352320021598F /* avatar.jpg */; }; 11 | 6E53E909194352320021598F /* me.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E907194352320021598F /* me.jpeg */; }; 12 | 6E53E911194352960021598F /* YRAboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E90B194352960021598F /* YRAboutViewController.swift */; }; 13 | 6E53E912194352960021598F /* YRAboutViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E90C194352960021598F /* YRAboutViewController.xib */; }; 14 | 6E53E913194352960021598F /* YRCommentsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E90D194352960021598F /* YRCommentsViewController.swift */; }; 15 | 6E53E914194352960021598F /* YRImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E90E194352960021598F /* YRImageViewController.swift */; }; 16 | 6E53E915194352960021598F /* YRJokeTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E90F194352960021598F /* YRJokeTableViewController.swift */; }; 17 | 6E53E916194352960021598F /* YRMainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E910194352960021598F /* YRMainViewController.swift */; }; 18 | 6E53E91F194352DE0021598F /* YRCommnentsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E918194352DE0021598F /* YRCommnentsCell.swift */; }; 19 | 6E53E920194352DE0021598F /* YRCommnentsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E919194352DE0021598F /* YRCommnentsCell.xib */; }; 20 | 6E53E921194352DE0021598F /* YRImageZoomingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E91A194352DE0021598F /* YRImageZoomingView.swift */; }; 21 | 6E53E922194352DE0021598F /* YRJokeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E91B194352DE0021598F /* YRJokeCell.swift */; }; 22 | 6E53E923194352DE0021598F /* YRJokeCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E91C194352DE0021598F /* YRJokeCell.xib */; }; 23 | 6E53E924194352DE0021598F /* YRRefreshView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E91D194352DE0021598F /* YRRefreshView.swift */; }; 24 | 6E53E925194352DE0021598F /* YRRefreshView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E91E194352DE0021598F /* YRRefreshView.xib */; }; 25 | 6E53E92D194353060021598F /* FileUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E927194353060021598F /* FileUtility.swift */; }; 26 | 6E53E92E194353060021598F /* NSDictionaryExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E928194353060021598F /* NSDictionaryExt.swift */; }; 27 | 6E53E92F194353060021598F /* NSStringExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E929194353060021598F /* NSStringExt.swift */; }; 28 | 6E53E930194353060021598F /* UIImageViewWebExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E92A194353060021598F /* UIImageViewWebExt.swift */; }; 29 | 6E53E931194353060021598F /* UIViewExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E92B194353060021598F /* UIViewExt.swift */; }; 30 | 6E53E932194353060021598F /* YRHttpRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E92C194353060021598F /* YRHttpRequest.swift */; }; 31 | 6E53E938194356810021598F /* 01.png in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E934194356810021598F /* 01.png */; }; 32 | 6E53E939194356810021598F /* 02.png in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E935194356810021598F /* 02.png */; }; 33 | 6E53E93A194356810021598F /* 03.png in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E936194356810021598F /* 03.png */; }; 34 | 6E53E93B194356810021598F /* 04.png in Resources */ = {isa = PBXBuildFile; fileRef = 6E53E937194356810021598F /* 04.png */; }; 35 | 6ED8F37E194088F200644CB6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED8F37D194088F200644CB6 /* AppDelegate.swift */; }; 36 | 6ED8F380194088F200644CB6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6ED8F37F194088F200644CB6 /* Images.xcassets */; }; 37 | 6ED8F38C194088F300644CB6 /* JokeClient_SwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED8F38B194088F300644CB6 /* JokeClient_SwiftTests.swift */; }; 38 | /* End PBXBuildFile section */ 39 | 40 | /* Begin PBXContainerItemProxy section */ 41 | 6ED8F386194088F300644CB6 /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = 6ED8F370194088F200644CB6 /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = 6ED8F377194088F200644CB6; 46 | remoteInfo = "JokeClient-Swift"; 47 | }; 48 | /* End PBXContainerItemProxy section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | 6E53E906194352320021598F /* avatar.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = avatar.jpg; sourceTree = ""; }; 52 | 6E53E907194352320021598F /* me.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = me.jpeg; sourceTree = ""; }; 53 | 6E53E90B194352960021598F /* YRAboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRAboutViewController.swift; sourceTree = ""; }; 54 | 6E53E90C194352960021598F /* YRAboutViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = YRAboutViewController.xib; sourceTree = ""; }; 55 | 6E53E90D194352960021598F /* YRCommentsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRCommentsViewController.swift; sourceTree = ""; }; 56 | 6E53E90E194352960021598F /* YRImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRImageViewController.swift; sourceTree = ""; }; 57 | 6E53E90F194352960021598F /* YRJokeTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRJokeTableViewController.swift; sourceTree = ""; }; 58 | 6E53E910194352960021598F /* YRMainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRMainViewController.swift; sourceTree = ""; }; 59 | 6E53E918194352DE0021598F /* YRCommnentsCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRCommnentsCell.swift; sourceTree = ""; }; 60 | 6E53E919194352DE0021598F /* YRCommnentsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = YRCommnentsCell.xib; sourceTree = ""; }; 61 | 6E53E91A194352DE0021598F /* YRImageZoomingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRImageZoomingView.swift; sourceTree = ""; }; 62 | 6E53E91B194352DE0021598F /* YRJokeCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRJokeCell.swift; sourceTree = ""; }; 63 | 6E53E91C194352DE0021598F /* YRJokeCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = YRJokeCell.xib; sourceTree = ""; }; 64 | 6E53E91D194352DE0021598F /* YRRefreshView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRRefreshView.swift; sourceTree = ""; }; 65 | 6E53E91E194352DE0021598F /* YRRefreshView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = YRRefreshView.xib; sourceTree = ""; }; 66 | 6E53E927194353060021598F /* FileUtility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtility.swift; sourceTree = ""; }; 67 | 6E53E928194353060021598F /* NSDictionaryExt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSDictionaryExt.swift; sourceTree = ""; }; 68 | 6E53E929194353060021598F /* NSStringExt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSStringExt.swift; sourceTree = ""; }; 69 | 6E53E92A194353060021598F /* UIImageViewWebExt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageViewWebExt.swift; sourceTree = ""; }; 70 | 6E53E92B194353060021598F /* UIViewExt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewExt.swift; sourceTree = ""; }; 71 | 6E53E92C194353060021598F /* YRHttpRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YRHttpRequest.swift; sourceTree = ""; }; 72 | 6E53E934194356810021598F /* 01.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 01.png; sourceTree = ""; }; 73 | 6E53E935194356810021598F /* 02.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 02.png; sourceTree = ""; }; 74 | 6E53E936194356810021598F /* 03.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 03.png; sourceTree = ""; }; 75 | 6E53E937194356810021598F /* 04.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 04.png; sourceTree = ""; }; 76 | 6ED8F378194088F200644CB6 /* JokeClient-Swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "JokeClient-Swift.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 77 | 6ED8F37C194088F200644CB6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78 | 6ED8F37D194088F200644CB6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 79 | 6ED8F37F194088F200644CB6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 80 | 6ED8F385194088F300644CB6 /* JokeClient-SwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "JokeClient-SwiftTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 81 | 6ED8F38A194088F300644CB6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 82 | 6ED8F38B194088F300644CB6 /* JokeClient_SwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JokeClient_SwiftTests.swift; sourceTree = ""; }; 83 | /* End PBXFileReference section */ 84 | 85 | /* Begin PBXFrameworksBuildPhase section */ 86 | 6ED8F375194088F200644CB6 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | 6ED8F382194088F300644CB6 /* Frameworks */ = { 94 | isa = PBXFrameworksBuildPhase; 95 | buildActionMask = 2147483647; 96 | files = ( 97 | ); 98 | runOnlyForDeploymentPostprocessing = 0; 99 | }; 100 | /* End PBXFrameworksBuildPhase section */ 101 | 102 | /* Begin PBXGroup section */ 103 | 6E53E905194352320021598F /* image */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 6E53E906194352320021598F /* avatar.jpg */, 107 | 6E53E907194352320021598F /* me.jpeg */, 108 | ); 109 | path = image; 110 | sourceTree = ""; 111 | }; 112 | 6E53E90A194352960021598F /* ViewController */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 6E53E90F194352960021598F /* YRJokeTableViewController.swift */, 116 | 6E53E90B194352960021598F /* YRAboutViewController.swift */, 117 | 6E53E90C194352960021598F /* YRAboutViewController.xib */, 118 | 6E53E90D194352960021598F /* YRCommentsViewController.swift */, 119 | 6E53E90E194352960021598F /* YRImageViewController.swift */, 120 | 6E53E910194352960021598F /* YRMainViewController.swift */, 121 | ); 122 | path = ViewController; 123 | sourceTree = ""; 124 | }; 125 | 6E53E917194352DE0021598F /* View */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 6E53E918194352DE0021598F /* YRCommnentsCell.swift */, 129 | 6E53E919194352DE0021598F /* YRCommnentsCell.xib */, 130 | 6E53E91A194352DE0021598F /* YRImageZoomingView.swift */, 131 | 6E53E91B194352DE0021598F /* YRJokeCell.swift */, 132 | 6E53E91C194352DE0021598F /* YRJokeCell.xib */, 133 | 6E53E91D194352DE0021598F /* YRRefreshView.swift */, 134 | 6E53E91E194352DE0021598F /* YRRefreshView.xib */, 135 | ); 136 | path = View; 137 | sourceTree = ""; 138 | }; 139 | 6E53E926194353060021598F /* Utility */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 6E53E927194353060021598F /* FileUtility.swift */, 143 | 6E53E928194353060021598F /* NSDictionaryExt.swift */, 144 | 6E53E929194353060021598F /* NSStringExt.swift */, 145 | 6E53E92A194353060021598F /* UIImageViewWebExt.swift */, 146 | 6E53E92B194353060021598F /* UIViewExt.swift */, 147 | 6E53E92C194353060021598F /* YRHttpRequest.swift */, 148 | ); 149 | path = Utility; 150 | sourceTree = ""; 151 | }; 152 | 6E53E933194356810021598F /* screenshoot */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 6E53E934194356810021598F /* 01.png */, 156 | 6E53E935194356810021598F /* 02.png */, 157 | 6E53E936194356810021598F /* 03.png */, 158 | 6E53E937194356810021598F /* 04.png */, 159 | ); 160 | path = screenshoot; 161 | sourceTree = ""; 162 | }; 163 | 6ED8F36F194088F200644CB6 = { 164 | isa = PBXGroup; 165 | children = ( 166 | 6ED8F37A194088F200644CB6 /* JokeClient-Swift */, 167 | 6ED8F388194088F300644CB6 /* JokeClient-SwiftTests */, 168 | 6ED8F379194088F200644CB6 /* Products */, 169 | ); 170 | sourceTree = ""; 171 | }; 172 | 6ED8F379194088F200644CB6 /* Products */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 6ED8F378194088F200644CB6 /* JokeClient-Swift.app */, 176 | 6ED8F385194088F300644CB6 /* JokeClient-SwiftTests.xctest */, 177 | ); 178 | name = Products; 179 | sourceTree = ""; 180 | }; 181 | 6ED8F37A194088F200644CB6 /* JokeClient-Swift */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 6ED8F37D194088F200644CB6 /* AppDelegate.swift */, 185 | 6E53E917194352DE0021598F /* View */, 186 | 6E53E90A194352960021598F /* ViewController */, 187 | 6E53E926194353060021598F /* Utility */, 188 | 6E53E933194356810021598F /* screenshoot */, 189 | 6E53E905194352320021598F /* image */, 190 | 6ED8F37F194088F200644CB6 /* Images.xcassets */, 191 | 6ED8F37B194088F200644CB6 /* Supporting Files */, 192 | ); 193 | path = "JokeClient-Swift"; 194 | sourceTree = ""; 195 | }; 196 | 6ED8F37B194088F200644CB6 /* Supporting Files */ = { 197 | isa = PBXGroup; 198 | children = ( 199 | 6ED8F37C194088F200644CB6 /* Info.plist */, 200 | ); 201 | name = "Supporting Files"; 202 | sourceTree = ""; 203 | }; 204 | 6ED8F388194088F300644CB6 /* JokeClient-SwiftTests */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | 6ED8F38B194088F300644CB6 /* JokeClient_SwiftTests.swift */, 208 | 6ED8F389194088F300644CB6 /* Supporting Files */, 209 | ); 210 | path = "JokeClient-SwiftTests"; 211 | sourceTree = ""; 212 | }; 213 | 6ED8F389194088F300644CB6 /* Supporting Files */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | 6ED8F38A194088F300644CB6 /* Info.plist */, 217 | ); 218 | name = "Supporting Files"; 219 | sourceTree = ""; 220 | }; 221 | /* End PBXGroup section */ 222 | 223 | /* Begin PBXNativeTarget section */ 224 | 6ED8F377194088F200644CB6 /* JokeClient-Swift */ = { 225 | isa = PBXNativeTarget; 226 | buildConfigurationList = 6ED8F38F194088F300644CB6 /* Build configuration list for PBXNativeTarget "JokeClient-Swift" */; 227 | buildPhases = ( 228 | 6ED8F374194088F200644CB6 /* Sources */, 229 | 6ED8F375194088F200644CB6 /* Frameworks */, 230 | 6ED8F376194088F200644CB6 /* Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | ); 236 | name = "JokeClient-Swift"; 237 | productName = "JokeClient-Swift"; 238 | productReference = 6ED8F378194088F200644CB6 /* JokeClient-Swift.app */; 239 | productType = "com.apple.product-type.application"; 240 | }; 241 | 6ED8F384194088F300644CB6 /* JokeClient-SwiftTests */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = 6ED8F392194088F300644CB6 /* Build configuration list for PBXNativeTarget "JokeClient-SwiftTests" */; 244 | buildPhases = ( 245 | 6ED8F381194088F300644CB6 /* Sources */, 246 | 6ED8F382194088F300644CB6 /* Frameworks */, 247 | 6ED8F383194088F300644CB6 /* Resources */, 248 | ); 249 | buildRules = ( 250 | ); 251 | dependencies = ( 252 | 6ED8F387194088F300644CB6 /* PBXTargetDependency */, 253 | ); 254 | name = "JokeClient-SwiftTests"; 255 | productName = "JokeClient-SwiftTests"; 256 | productReference = 6ED8F385194088F300644CB6 /* JokeClient-SwiftTests.xctest */; 257 | productType = "com.apple.product-type.bundle.unit-test"; 258 | }; 259 | /* End PBXNativeTarget section */ 260 | 261 | /* Begin PBXProject section */ 262 | 6ED8F370194088F200644CB6 /* Project object */ = { 263 | isa = PBXProject; 264 | attributes = { 265 | LastSwiftUpdateCheck = 0710; 266 | LastUpgradeCheck = 0900; 267 | ORGANIZATIONNAME = YANGReal; 268 | TargetAttributes = { 269 | 6ED8F377194088F200644CB6 = { 270 | CreatedOnToolsVersion = 6.0; 271 | DevelopmentTeam = PT7S3D7UCK; 272 | LastSwiftMigration = 0830; 273 | }; 274 | 6ED8F384194088F300644CB6 = { 275 | CreatedOnToolsVersion = 6.0; 276 | LastSwiftMigration = 0830; 277 | TestTargetID = 6ED8F377194088F200644CB6; 278 | }; 279 | }; 280 | }; 281 | buildConfigurationList = 6ED8F373194088F200644CB6 /* Build configuration list for PBXProject "JokeClient-Swift" */; 282 | compatibilityVersion = "Xcode 3.2"; 283 | developmentRegion = English; 284 | hasScannedForEncodings = 0; 285 | knownRegions = ( 286 | en, 287 | ); 288 | mainGroup = 6ED8F36F194088F200644CB6; 289 | productRefGroup = 6ED8F379194088F200644CB6 /* Products */; 290 | projectDirPath = ""; 291 | projectRoot = ""; 292 | targets = ( 293 | 6ED8F377194088F200644CB6 /* JokeClient-Swift */, 294 | 6ED8F384194088F300644CB6 /* JokeClient-SwiftTests */, 295 | ); 296 | }; 297 | /* End PBXProject section */ 298 | 299 | /* Begin PBXResourcesBuildPhase section */ 300 | 6ED8F376194088F200644CB6 /* Resources */ = { 301 | isa = PBXResourcesBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | 6E53E93A194356810021598F /* 03.png in Resources */, 305 | 6ED8F380194088F200644CB6 /* Images.xcassets in Resources */, 306 | 6E53E920194352DE0021598F /* YRCommnentsCell.xib in Resources */, 307 | 6E53E93B194356810021598F /* 04.png in Resources */, 308 | 6E53E938194356810021598F /* 01.png in Resources */, 309 | 6E53E909194352320021598F /* me.jpeg in Resources */, 310 | 6E53E923194352DE0021598F /* YRJokeCell.xib in Resources */, 311 | 6E53E908194352320021598F /* avatar.jpg in Resources */, 312 | 6E53E912194352960021598F /* YRAboutViewController.xib in Resources */, 313 | 6E53E925194352DE0021598F /* YRRefreshView.xib in Resources */, 314 | 6E53E939194356810021598F /* 02.png in Resources */, 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | }; 318 | 6ED8F383194088F300644CB6 /* Resources */ = { 319 | isa = PBXResourcesBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | }; 325 | /* End PBXResourcesBuildPhase section */ 326 | 327 | /* Begin PBXSourcesBuildPhase section */ 328 | 6ED8F374194088F200644CB6 /* Sources */ = { 329 | isa = PBXSourcesBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | 6E53E924194352DE0021598F /* YRRefreshView.swift in Sources */, 333 | 6E53E921194352DE0021598F /* YRImageZoomingView.swift in Sources */, 334 | 6E53E932194353060021598F /* YRHttpRequest.swift in Sources */, 335 | 6E53E92D194353060021598F /* FileUtility.swift in Sources */, 336 | 6E53E91F194352DE0021598F /* YRCommnentsCell.swift in Sources */, 337 | 6E53E916194352960021598F /* YRMainViewController.swift in Sources */, 338 | 6E53E915194352960021598F /* YRJokeTableViewController.swift in Sources */, 339 | 6E53E914194352960021598F /* YRImageViewController.swift in Sources */, 340 | 6E53E911194352960021598F /* YRAboutViewController.swift in Sources */, 341 | 6E53E92E194353060021598F /* NSDictionaryExt.swift in Sources */, 342 | 6E53E930194353060021598F /* UIImageViewWebExt.swift in Sources */, 343 | 6E53E913194352960021598F /* YRCommentsViewController.swift in Sources */, 344 | 6ED8F37E194088F200644CB6 /* AppDelegate.swift in Sources */, 345 | 6E53E931194353060021598F /* UIViewExt.swift in Sources */, 346 | 6E53E922194352DE0021598F /* YRJokeCell.swift in Sources */, 347 | 6E53E92F194353060021598F /* NSStringExt.swift in Sources */, 348 | ); 349 | runOnlyForDeploymentPostprocessing = 0; 350 | }; 351 | 6ED8F381194088F300644CB6 /* Sources */ = { 352 | isa = PBXSourcesBuildPhase; 353 | buildActionMask = 2147483647; 354 | files = ( 355 | 6ED8F38C194088F300644CB6 /* JokeClient_SwiftTests.swift in Sources */, 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | }; 359 | /* End PBXSourcesBuildPhase section */ 360 | 361 | /* Begin PBXTargetDependency section */ 362 | 6ED8F387194088F300644CB6 /* PBXTargetDependency */ = { 363 | isa = PBXTargetDependency; 364 | target = 6ED8F377194088F200644CB6 /* JokeClient-Swift */; 365 | targetProxy = 6ED8F386194088F300644CB6 /* PBXContainerItemProxy */; 366 | }; 367 | /* End PBXTargetDependency section */ 368 | 369 | /* Begin XCBuildConfiguration section */ 370 | 6ED8F38D194088F300644CB6 /* Debug */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ALWAYS_SEARCH_USER_PATHS = NO; 374 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 375 | CLANG_CXX_LIBRARY = "libc++"; 376 | CLANG_ENABLE_MODULES = YES; 377 | CLANG_ENABLE_OBJC_ARC = YES; 378 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 379 | CLANG_WARN_BOOL_CONVERSION = YES; 380 | CLANG_WARN_COMMA = YES; 381 | CLANG_WARN_CONSTANT_CONVERSION = YES; 382 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 383 | CLANG_WARN_EMPTY_BODY = YES; 384 | CLANG_WARN_ENUM_CONVERSION = YES; 385 | CLANG_WARN_INFINITE_RECURSION = YES; 386 | CLANG_WARN_INT_CONVERSION = YES; 387 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 388 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 389 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 390 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 391 | CLANG_WARN_STRICT_PROTOTYPES = YES; 392 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 393 | CLANG_WARN_UNREACHABLE_CODE = YES; 394 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 395 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 396 | COPY_PHASE_STRIP = NO; 397 | ENABLE_STRICT_OBJC_MSGSEND = YES; 398 | ENABLE_TESTABILITY = YES; 399 | GCC_C_LANGUAGE_STANDARD = gnu99; 400 | GCC_DYNAMIC_NO_PIC = NO; 401 | GCC_NO_COMMON_BLOCKS = YES; 402 | GCC_OPTIMIZATION_LEVEL = 0; 403 | GCC_PREPROCESSOR_DEFINITIONS = ( 404 | "DEBUG=1", 405 | "$(inherited)", 406 | ); 407 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 408 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 409 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 410 | GCC_WARN_UNDECLARED_SELECTOR = YES; 411 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 412 | GCC_WARN_UNUSED_FUNCTION = YES; 413 | GCC_WARN_UNUSED_VARIABLE = YES; 414 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 415 | METAL_ENABLE_DEBUG_INFO = YES; 416 | ONLY_ACTIVE_ARCH = YES; 417 | SDKROOT = iphoneos; 418 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 419 | }; 420 | name = Debug; 421 | }; 422 | 6ED8F38E194088F300644CB6 /* Release */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | ALWAYS_SEARCH_USER_PATHS = NO; 426 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 427 | CLANG_CXX_LIBRARY = "libc++"; 428 | CLANG_ENABLE_MODULES = YES; 429 | CLANG_ENABLE_OBJC_ARC = YES; 430 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 431 | CLANG_WARN_BOOL_CONVERSION = YES; 432 | CLANG_WARN_COMMA = YES; 433 | CLANG_WARN_CONSTANT_CONVERSION = YES; 434 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 435 | CLANG_WARN_EMPTY_BODY = YES; 436 | CLANG_WARN_ENUM_CONVERSION = YES; 437 | CLANG_WARN_INFINITE_RECURSION = YES; 438 | CLANG_WARN_INT_CONVERSION = YES; 439 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 440 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 441 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 442 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 443 | CLANG_WARN_STRICT_PROTOTYPES = YES; 444 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 445 | CLANG_WARN_UNREACHABLE_CODE = YES; 446 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 447 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 448 | COPY_PHASE_STRIP = YES; 449 | ENABLE_NS_ASSERTIONS = NO; 450 | ENABLE_STRICT_OBJC_MSGSEND = YES; 451 | GCC_C_LANGUAGE_STANDARD = gnu99; 452 | GCC_NO_COMMON_BLOCKS = YES; 453 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 454 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 455 | GCC_WARN_UNDECLARED_SELECTOR = YES; 456 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 457 | GCC_WARN_UNUSED_FUNCTION = YES; 458 | GCC_WARN_UNUSED_VARIABLE = YES; 459 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 460 | METAL_ENABLE_DEBUG_INFO = NO; 461 | SDKROOT = iphoneos; 462 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 463 | VALIDATE_PRODUCT = YES; 464 | }; 465 | name = Release; 466 | }; 467 | 6ED8F390194088F300644CB6 /* Debug */ = { 468 | isa = XCBuildConfiguration; 469 | buildSettings = { 470 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 471 | CODE_SIGN_IDENTITY = "iPhone Developer"; 472 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 473 | DEVELOPMENT_TEAM = PT7S3D7UCK; 474 | INFOPLIST_FILE = "JokeClient-Swift/Info.plist"; 475 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 476 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 477 | ONLY_ACTIVE_ARCH = YES; 478 | PRODUCT_BUNDLE_IDENTIFIER = com.yangreal.joke; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | PROVISIONING_PROFILE = ""; 481 | SWIFT_VERSION = 3.0; 482 | }; 483 | name = Debug; 484 | }; 485 | 6ED8F391194088F300644CB6 /* Release */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 489 | CODE_SIGN_IDENTITY = "iPhone Developer"; 490 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 491 | DEVELOPMENT_TEAM = PT7S3D7UCK; 492 | INFOPLIST_FILE = "JokeClient-Swift/Info.plist"; 493 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 494 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 495 | ONLY_ACTIVE_ARCH = YES; 496 | PRODUCT_BUNDLE_IDENTIFIER = com.yangreal.joke; 497 | PRODUCT_NAME = "$(TARGET_NAME)"; 498 | PROVISIONING_PROFILE = ""; 499 | SWIFT_VERSION = 3.0; 500 | }; 501 | name = Release; 502 | }; 503 | 6ED8F393194088F300644CB6 /* Debug */ = { 504 | isa = XCBuildConfiguration; 505 | buildSettings = { 506 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/JokeClient-Swift.app/JokeClient-Swift"; 507 | FRAMEWORK_SEARCH_PATHS = ( 508 | "$(SDKROOT)/Developer/Library/Frameworks", 509 | "$(inherited)", 510 | ); 511 | GCC_PREPROCESSOR_DEFINITIONS = ( 512 | "DEBUG=1", 513 | "$(inherited)", 514 | ); 515 | INFOPLIST_FILE = "JokeClient-SwiftTests/Info.plist"; 516 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 517 | METAL_ENABLE_DEBUG_INFO = YES; 518 | PRODUCT_BUNDLE_IDENTIFIER = "YANGReal.${PRODUCT_NAME:rfc1034identifier}"; 519 | PRODUCT_NAME = "$(TARGET_NAME)"; 520 | SWIFT_VERSION = 3.0; 521 | TEST_HOST = "$(BUNDLE_LOADER)"; 522 | }; 523 | name = Debug; 524 | }; 525 | 6ED8F394194088F300644CB6 /* Release */ = { 526 | isa = XCBuildConfiguration; 527 | buildSettings = { 528 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/JokeClient-Swift.app/JokeClient-Swift"; 529 | FRAMEWORK_SEARCH_PATHS = ( 530 | "$(SDKROOT)/Developer/Library/Frameworks", 531 | "$(inherited)", 532 | ); 533 | INFOPLIST_FILE = "JokeClient-SwiftTests/Info.plist"; 534 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 535 | METAL_ENABLE_DEBUG_INFO = NO; 536 | PRODUCT_BUNDLE_IDENTIFIER = "YANGReal.${PRODUCT_NAME:rfc1034identifier}"; 537 | PRODUCT_NAME = "$(TARGET_NAME)"; 538 | SWIFT_VERSION = 3.0; 539 | TEST_HOST = "$(BUNDLE_LOADER)"; 540 | }; 541 | name = Release; 542 | }; 543 | /* End XCBuildConfiguration section */ 544 | 545 | /* Begin XCConfigurationList section */ 546 | 6ED8F373194088F200644CB6 /* Build configuration list for PBXProject "JokeClient-Swift" */ = { 547 | isa = XCConfigurationList; 548 | buildConfigurations = ( 549 | 6ED8F38D194088F300644CB6 /* Debug */, 550 | 6ED8F38E194088F300644CB6 /* Release */, 551 | ); 552 | defaultConfigurationIsVisible = 0; 553 | defaultConfigurationName = Release; 554 | }; 555 | 6ED8F38F194088F300644CB6 /* Build configuration list for PBXNativeTarget "JokeClient-Swift" */ = { 556 | isa = XCConfigurationList; 557 | buildConfigurations = ( 558 | 6ED8F390194088F300644CB6 /* Debug */, 559 | 6ED8F391194088F300644CB6 /* Release */, 560 | ); 561 | defaultConfigurationIsVisible = 0; 562 | defaultConfigurationName = Release; 563 | }; 564 | 6ED8F392194088F300644CB6 /* Build configuration list for PBXNativeTarget "JokeClient-SwiftTests" */ = { 565 | isa = XCConfigurationList; 566 | buildConfigurations = ( 567 | 6ED8F393194088F300644CB6 /* Debug */, 568 | 6ED8F394194088F300644CB6 /* Release */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | /* End XCConfigurationList section */ 574 | }; 575 | rootObject = 6ED8F370194088F200644CB6 /* Project object */; 576 | } 577 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/project.xcworkspace/xcshareddata/JokeClient-Swift.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 200A44B7-C478-450D-A599-33E1F0D28FED 9 | IDESourceControlProjectName 10 | JokeClient-Swift 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 636A33E322DB6ECA2A08363DE5784B1D75405E0C 14 | https://github.com/YANGReal/JokeClient-Swift.git 15 | 16 | IDESourceControlProjectPath 17 | JokeClient-Swift.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 636A33E322DB6ECA2A08363DE5784B1D75405E0C 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/YANGReal/JokeClient-Swift.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 636A33E322DB6ECA2A08363DE5784B1D75405E0C 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 636A33E322DB6ECA2A08363DE5784B1D75405E0C 36 | IDESourceControlWCCName 37 | JokeClient-Swift 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/project.xcworkspace/xcuserdata/appdev.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift.xcodeproj/project.xcworkspace/xcuserdata/appdev.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/project.xcworkspace/xcuserdata/ruiyang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift.xcodeproj/project.xcworkspace/xcuserdata/ruiyang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/project.xcworkspace/xcuserdata/yangreal.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift.xcodeproj/project.xcworkspace/xcuserdata/yangreal.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/appdev.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/appdev.xcuserdatad/xcschemes/JokeClient-Swift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/appdev.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JokeClient-Swift.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 6ED8F377194088F200644CB6 16 | 17 | primary 18 | 19 | 20 | 6ED8F384194088F300644CB6 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/ruiyang.xcuserdatad/xcschemes/JokeClient-Swift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/ruiyang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JokeClient-Swift.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 6ED8F377194088F200644CB6 16 | 17 | primary 18 | 19 | 20 | 6ED8F384194088F300644CB6 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/yangreal.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/yangreal.xcuserdatad/xcschemes/JokeClient-Swift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /JokeClient-Swift.xcodeproj/xcuserdata/yangreal.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JokeClient-Swift.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 6ED8F377194088F200644CB6 16 | 17 | primary 18 | 19 | 20 | 6ED8F384194088F300644CB6 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /JokeClient-Swift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-5. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? ) -> Bool { 17 | self.window = UIWindow(frame: UIScreen.main.bounds) 18 | // Override point for customization after application launch. 19 | let mainViewController = YRMainViewController(nibName:nil, bundle: nil) 20 | let navigationViewController = UINavigationController(rootViewController: mainViewController) 21 | 22 | self.window!.rootViewController = navigationViewController 23 | //self.window!.backgroundColor = UIColor.whiteColor() 24 | self.window!.makeKeyAndVisible() 25 | return true 26 | } 27 | 28 | func applicationWillResignActive(_ application: UIApplication) { 29 | // 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. 30 | // 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. 31 | } 32 | 33 | func applicationDidEnterBackground(_ application: UIApplication) { 34 | // 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. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | func applicationWillEnterForeground(_ application: UIApplication) { 39 | // 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. 40 | } 41 | 42 | func applicationDidBecomeActive(_ application: UIApplication) { 43 | // 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. 44 | } 45 | 46 | func applicationWillTerminate(_ application: UIApplication) { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /JokeClient-Swift/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/1136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/1136.png -------------------------------------------------------------------------------- /JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/1242.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/1242.png -------------------------------------------------------------------------------- /JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/750.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/750.png -------------------------------------------------------------------------------- /JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/960.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/960.png -------------------------------------------------------------------------------- /JokeClient-Swift/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "736h", 7 | "filename" : "1242.png", 8 | "minimum-system-version" : "8.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "extent" : "full-screen", 14 | "idiom" : "iphone", 15 | "subtype" : "667h", 16 | "filename" : "750.png", 17 | "minimum-system-version" : "8.0", 18 | "orientation" : "portrait", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "orientation" : "portrait", 23 | "idiom" : "iphone", 24 | "filename" : "960.png", 25 | "extent" : "full-screen", 26 | "minimum-system-version" : "7.0", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "extent" : "full-screen", 31 | "idiom" : "iphone", 32 | "subtype" : "retina4", 33 | "filename" : "1136.png", 34 | "minimum-system-version" : "7.0", 35 | "orientation" : "portrait", 36 | "scale" : "2x" 37 | } 38 | ], 39 | "info" : { 40 | "version" : 1, 41 | "author" : "xcode" 42 | } 43 | } -------------------------------------------------------------------------------- /JokeClient-Swift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UIRequiredDeviceCapabilities 31 | 32 | armv7 33 | 34 | UISupportedInterfaceOrientations 35 | 36 | UIInterfaceOrientationPortrait 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /JokeClient-Swift/Utility/FileUtility.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FileUtility.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-7. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FileUtility: NSObject { 12 | 13 | 14 | class func cachePath(_ fileName:String)->String 15 | { 16 | var arr = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) 17 | let path = arr[0] 18 | return "\(path)/\(fileName)" 19 | } 20 | 21 | 22 | class func imageCacheToPath(_ path:String,image:Data)->Bool 23 | { 24 | return ((try? image.write(to: URL(fileURLWithPath: path), options: [.atomic])) != nil) 25 | } 26 | 27 | class func imageDataFromPath(_ path:String)->AnyObject 28 | { 29 | let exist = FileManager.default.fileExists(atPath: path) 30 | if exist 31 | { 32 | 33 | _ = try? Data(contentsOf: URL(fileURLWithPath: path)); 34 | //var img:UIImage? = UIImage(data:data!) 35 | //return img ?? NSNull() 36 | let img = UIImage(contentsOfFile: path) 37 | 38 | let url:URL? = URL(fileURLWithPath: path) 39 | let dd = FileManager.default.contents(atPath: url!.path) 40 | _ = UIImage(data:dd!) 41 | 42 | if img != nil 43 | { 44 | return img! 45 | } 46 | else 47 | { 48 | return NSNull() 49 | } 50 | } 51 | return NSNull() 52 | } 53 | 54 | 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /JokeClient-Swift/Utility/NSDictionaryExt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary-Null.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-7. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | extension NSDictionary { 12 | 13 | 14 | func stringAttributeForKey(_ key:String)->String 15 | { 16 | guard let obj = self[key] else { 17 | return "" 18 | } 19 | if let str = obj as? String 20 | { 21 | return str 22 | } 23 | else if let num = obj as? NSNumber 24 | { 25 | return num.stringValue 26 | } 27 | else 28 | { 29 | return "" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /JokeClient-Swift/Utility/NSStringExt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSStringExtension.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-6. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | import UIKit 9 | import Foundation 10 | 11 | extension String { 12 | 13 | 14 | func stringHeightWith(_ fontSize:CGFloat,width:CGFloat)->CGFloat 15 | 16 | { 17 | let font = UIFont.systemFont(ofSize: fontSize) 18 | let size = CGSize(width: width,height: CGFloat.greatestFiniteMagnitude) 19 | let paragraphStyle = NSMutableParagraphStyle() 20 | paragraphStyle.lineBreakMode = .byWordWrapping; 21 | let attributes = [NSFontAttributeName:font, 22 | NSParagraphStyleAttributeName:paragraphStyle.copy()] 23 | 24 | let text = self as NSString 25 | let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: attributes, context:nil) 26 | return rect.size.height 27 | } 28 | 29 | func dateStringFromTimestamp(_ timeStamp:NSString)->String 30 | { 31 | let ts = timeStamp.doubleValue 32 | let formatter = DateFormatter () 33 | formatter.dateFormat = "yyyy年MM月dd日 HH:MM:ss" 34 | let date = Date(timeIntervalSince1970 : ts) 35 | return formatter.string(from: date) 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /JokeClient-Swift/Utility/UIImageViewWebExt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageViewWebExt.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-5. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | 12 | extension UIImageView 13 | { 14 | func setImage(_ urlString:String,placeHolder:UIImage!) 15 | { 16 | 17 | let url = URL(string: urlString) 18 | let cacheFilename = url!.lastPathComponent 19 | let cachePath = FileUtility.cachePath(cacheFilename) 20 | let image : AnyObject = FileUtility.imageDataFromPath(cachePath) 21 | // println(cachePath) 22 | if image as! NSObject != NSNull() 23 | { 24 | self.image = image as? UIImage 25 | } 26 | else 27 | { 28 | let req = URLRequest(url: url!) 29 | let queue = OperationQueue(); 30 | NSURLConnection.sendAsynchronousRequest(req, queue: queue, completionHandler: { response, data, error in 31 | if (error != nil) 32 | { 33 | DispatchQueue.main.async(execute: { 34 | print(error!) 35 | self.image = placeHolder 36 | }) 37 | } 38 | else 39 | { 40 | DispatchQueue.main.async(execute: { 41 | 42 | let image = UIImage(data: data!) 43 | if (image == nil) 44 | { 45 | 46 | print("image is nil and url fail=\(urlString)") 47 | self.image = placeHolder 48 | } 49 | else 50 | { 51 | self.image = image 52 | let bIsSuccess = FileUtility.imageCacheToPath(cachePath,image:data!) 53 | if !bIsSuccess 54 | { 55 | print("*******cache fail,path=\(cachePath)") 56 | } 57 | } 58 | }) 59 | } 60 | }) 61 | 62 | } 63 | 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /JokeClient-Swift/Utility/UIViewExt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView-Frame.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-7. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | extension UIView { 12 | 13 | func x()->CGFloat 14 | { 15 | return self.frame.origin.x 16 | } 17 | func right()-> CGFloat 18 | { 19 | return self.frame.origin.x + self.frame.size.width 20 | } 21 | func y()->CGFloat 22 | { 23 | return self.frame.origin.y 24 | } 25 | func bottom()->CGFloat 26 | { 27 | return self.frame.origin.y + self.frame.size.height 28 | } 29 | func width()->CGFloat 30 | { 31 | return self.frame.size.width 32 | } 33 | func height()-> CGFloat 34 | { 35 | return self.frame.size.height 36 | } 37 | 38 | func setX(_ x: CGFloat) 39 | { 40 | var rect:CGRect = self.frame 41 | rect.origin.x = x 42 | self.frame = rect 43 | } 44 | 45 | func setRight(_ right: CGFloat) 46 | { 47 | var rect:CGRect = self.frame 48 | rect.origin.x = right - rect.size.width 49 | self.frame = rect 50 | } 51 | 52 | func setY(_ y: CGFloat) 53 | { 54 | var rect:CGRect = self.frame 55 | rect.origin.y = y 56 | self.frame = rect 57 | } 58 | 59 | func setBottom(_ bottom: CGFloat) 60 | { 61 | var rect:CGRect = self.frame 62 | rect.origin.y = bottom - rect.size.height 63 | self.frame = rect 64 | } 65 | 66 | func setWidth(_ width: CGFloat) 67 | { 68 | var rect:CGRect = self.frame 69 | rect.size.width = width 70 | self.frame = rect 71 | } 72 | 73 | func setHeight(_ height: CGFloat) 74 | { 75 | var rect:CGRect = self.frame 76 | rect.size.height = height 77 | self.frame = rect 78 | } 79 | 80 | class func showAlertView(_ title:String,message:String) 81 | { 82 | let alert = UIAlertView() 83 | alert.title = title 84 | alert.message = message 85 | alert.addButton(withTitle: "好") 86 | alert.show() 87 | 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /JokeClient-Swift/Utility/YRHttpRequest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRHttpRequest.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-5. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | 12 | //class func connectionWithRequest(request: NSURLRequest!, delegate: AnyObject!) -> NSURLConnection! 13 | 14 | 15 | class YRHttpRequest: NSObject { 16 | 17 | override init() 18 | { 19 | super.init(); 20 | } 21 | 22 | class func requestWithURL(_ urlString:String,completionHandler:@escaping (_ data:AnyObject)->Void) 23 | { 24 | let URL = Foundation.URL(string: urlString); 25 | let req = URLRequest(url: URL!) 26 | let queue = OperationQueue(); 27 | NSURLConnection.sendAsynchronousRequest(req, queue: queue, completionHandler: { response, data, error in 28 | if (error != nil) 29 | { 30 | DispatchQueue.main.async(execute: { 31 | print(error!) 32 | completionHandler(NSNull()) 33 | }) 34 | } 35 | else 36 | { 37 | let jsonData = (try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as! NSDictionary 38 | 39 | DispatchQueue.main.async(execute: { 40 | completionHandler(jsonData) 41 | 42 | }) 43 | } 44 | }) 45 | } 46 | 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /JokeClient-Swift/View/YRCommnentsCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRCommnentsCell.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-7. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YRCommnentsCell: UITableViewCell { 12 | 13 | 14 | @IBOutlet var avatarView:UIImageView? 15 | @IBOutlet var nickLabel:UILabel? 16 | @IBOutlet var contentLabel:UILabel? 17 | @IBOutlet var floorLabel:UILabel? 18 | @IBOutlet var dateLabel:UILabel? 19 | 20 | 21 | var data :NSDictionary! 22 | 23 | 24 | 25 | 26 | override func awakeFromNib() { 27 | super.awakeFromNib() 28 | // Initialization code 29 | } 30 | 31 | override func setSelected(_ selected: Bool, animated: Bool) { 32 | super.setSelected(selected, animated: animated) 33 | 34 | // Configure the view for the selected state 35 | } 36 | 37 | override func layoutSubviews() 38 | { 39 | super.layoutSubviews() 40 | // var uid = self.data["id"] as String 41 | let user = self.data["user"] 42 | 43 | if user as! NSObject != NSNull() 44 | { 45 | let userDict = user as! NSDictionary 46 | self.nickLabel!.text = userDict["login"] as! NSString as String 47 | 48 | let icon = userDict["icon"] 49 | if icon as! NSObject != NSNull() 50 | { 51 | let userIcon = icon as! String 52 | let userId = userDict.stringAttributeForKey("id") as NSString; 53 | let prefixUserId = userId.substring(to: 3) 54 | let userImageURL = "http://pic.moumentei.com/system/avtnew/\(prefixUserId)/\(userId)/thumb/\(userIcon)" 55 | self.avatarView!.setImage(userImageURL,placeHolder: UIImage(named: "avatar.jpg")) 56 | } 57 | else 58 | { 59 | self.avatarView!.image = UIImage(named: "avatar.jpg") 60 | } 61 | 62 | let timeStamp = userDict.stringAttributeForKey("created_at") 63 | let date = timeStamp.dateStringFromTimestamp(timeStamp as NSString) 64 | self.dateLabel!.text = date 65 | 66 | } 67 | else 68 | { 69 | self.nickLabel!.text = "匿名" 70 | self.avatarView!.image = UIImage(named: "avatar.jpg") 71 | self.dateLabel!.text = "" 72 | 73 | } 74 | let content = self.data.stringAttributeForKey("content") 75 | let width = UIScreen.main.bounds.size.height 76 | let height = content.stringHeightWith(17,width:width-10*2) 77 | self.contentLabel!.setHeight(height) 78 | self.contentLabel!.text = content 79 | self.dateLabel!.setY(self.contentLabel!.bottom()) 80 | let floor = self.data.stringAttributeForKey("floor") 81 | self.floorLabel!.text = "\(floor)楼" 82 | // self.contentLabel?.backgroundColor = UIColor.redColor(); 83 | } 84 | 85 | 86 | 87 | 88 | 89 | class func cellHeightByData(_ data:NSDictionary)->CGFloat 90 | { 91 | let content = data.stringAttributeForKey("content") 92 | let width = UIScreen.main.bounds.size.height 93 | let height = content.stringHeightWith(17,width:width-10*2) 94 | return 53.0 + height + 24.0 95 | } 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /JokeClient-Swift/View/YRCommnentsCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 35 | 42 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /JokeClient-Swift/View/YRImageZoomingView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRImageZoomingVIew.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-7. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YRImageZoomingView: UIScrollView,UIScrollViewDelegate { 12 | 13 | 14 | var imageView:UIImageView? 15 | var imageURL:String! 16 | let placeHolder:UIImage = UIImage(named:"avatar.jpg")! 17 | 18 | override init(frame: CGRect) { 19 | super.init(frame: frame) 20 | // Initialization code 21 | self.delegate = self 22 | 23 | 24 | self.imageView = UIImageView(frame:self.bounds) 25 | self.imageView!.contentMode = .scaleAspectFit 26 | self.addSubview(self.imageView!) 27 | self.showsHorizontalScrollIndicator = false 28 | self.showsVerticalScrollIndicator = false 29 | self.backgroundColor = UIColor.clear 30 | self.minimumZoomScale = 1; 31 | self.maximumZoomScale = 3; 32 | 33 | let doubleTap = UITapGestureRecognizer(target: self, action: #selector(YRImageZoomingView.doubleTapped(_:))) 34 | doubleTap.numberOfTapsRequired = 2; 35 | self.addGestureRecognizer(doubleTap); 36 | 37 | } 38 | 39 | 40 | 41 | required init?(coder aDecoder: NSCoder) { 42 | fatalError("init(coder:) has not been implemented") 43 | } 44 | 45 | func doubleTapped(_ sender:UITapGestureRecognizer) 46 | { 47 | if self.zoomScale > 1.0 48 | { 49 | self.setZoomScale(1.0, animated:true); 50 | } 51 | else 52 | { 53 | let point = sender.location(in: self); 54 | self.zoom(to: CGRect(x: point.x-50, y: point.y-50, width: 100, height: 100), animated:true) 55 | } 56 | 57 | } 58 | 59 | 60 | func viewForZooming(in scrollView: UIScrollView)->UIView? 61 | { 62 | return self.imageView 63 | } 64 | 65 | override func layoutSubviews() 66 | { 67 | super.layoutSubviews() 68 | self.imageView!.setImage(self.imageURL,placeHolder:placeHolder) 69 | 70 | } 71 | /* 72 | // Only override drawRect: if you perform custom drawing. 73 | // An empty implementation adversely affects performance during animation. 74 | override func drawRect(rect: CGRect) 75 | { 76 | // Drawing code 77 | } 78 | */ 79 | 80 | } 81 | -------------------------------------------------------------------------------- /JokeClient-Swift/View/YRJokeCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRJokeCell.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-6. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | class YRJokeCell: UITableViewCell { 13 | 14 | @IBOutlet var avatarView:UIImageView? 15 | @IBOutlet var pictureView:UIImageView? 16 | @IBOutlet var nickLabel:UILabel? 17 | @IBOutlet var contentLabel:UILabel? 18 | @IBOutlet var likeLabel:UILabel? 19 | @IBOutlet var dislikeLabel:UILabel? 20 | @IBOutlet var commentLabel:UILabel? 21 | @IBOutlet var bottomView:UIView? 22 | var largeImageURL:String = "" 23 | var data :NSDictionary! 24 | 25 | //let avatarPlaceHolder = UIImage(named: "avatar.jpg") 26 | 27 | @IBAction func shareBtnClicked() 28 | { 29 | // self.delegate!.jokeCell(self, didClickShareButtonWithData:self.data) 30 | } 31 | 32 | override func awakeFromNib() { 33 | super.awakeFromNib() 34 | 35 | self.selectionStyle = .none 36 | 37 | 38 | let tap = UITapGestureRecognizer(target: self, action: #selector(YRJokeCell.imageViewTapped(_:))) 39 | self.pictureView!.addGestureRecognizer(tap) 40 | } 41 | 42 | override func setSelected(_ selected: Bool, animated: Bool) { 43 | super.setSelected(selected, animated: animated) 44 | 45 | // Configure the view for the selected state 46 | } 47 | 48 | override func layoutSubviews() 49 | { 50 | super.layoutSubviews() 51 | // var uid = self.data["id"] as String 52 | 53 | guard ((self.data) != nil) else{ 54 | return; 55 | } 56 | 57 | let user = self.data["user"] 58 | 59 | //if user as! NSObject != NSNull() 60 | if let userDictOp:NSDictionary = user as? NSDictionary 61 | { 62 | //var userDict = user as! NSDictionary 63 | let userDict = userDictOp 64 | self.nickLabel!.text = userDict["login"] as! String? 65 | 66 | let icon = userDict["icon"] //as NSString 67 | if icon as! NSObject != NSNull() 68 | { 69 | let userIcon = icon as! String 70 | if let idNumber = userDict["id"] as? NSNumber { 71 | let userId = idNumber.stringValue as NSString 72 | let prefixUserId = userId.substring(to: userId.length - 4) 73 | 74 | let userImageURL = "http://pic.qiushibaike.com/system/avtnew/\(prefixUserId)/\(userId)/medium/\(userIcon)" 75 | self.avatarView!.setImage(userImageURL,placeHolder: UIImage(named: "avatar.jpg")) 76 | } 77 | 78 | } 79 | else 80 | { 81 | self.avatarView!.image = UIImage(named: "avatar.jpg") 82 | } 83 | } 84 | else 85 | { 86 | self.nickLabel!.text = "匿名" 87 | self.avatarView!.image = UIImage(named: "avatar.jpg") 88 | 89 | } 90 | let content = self.data.stringAttributeForKey("content") 91 | let width = UIScreen.main.bounds.size.width; 92 | let height = content.stringHeightWith(17,width:width-10*2) 93 | 94 | self.contentLabel!.setHeight(height) 95 | self.contentLabel!.text = content 96 | 97 | let imgSrc = self.data.stringAttributeForKey("image") as NSString 98 | if imgSrc.length == 0 99 | { 100 | self.pictureView!.isHidden = true 101 | self.bottomView!.setY(self.contentLabel!.bottom()) 102 | } 103 | else 104 | { 105 | let imageId = self.data.stringAttributeForKey("id") as NSString 106 | let prefiximageId = imageId.substring(to: imageId.length - 4) 107 | let imagURL = "http://pic.qiushibaike.com/system/pictures/\(prefiximageId)/\(imageId)/small/\(imgSrc)" 108 | self.pictureView!.isHidden = false 109 | self.pictureView!.setImage(imagURL,placeHolder: UIImage(named: "avatar.jpg")) 110 | self.largeImageURL = "http://pic.qiushibaike.com/system/pictures/\(prefiximageId)/\(imageId)/medium/\(imgSrc)" 111 | self.pictureView!.setY(self.contentLabel!.bottom()+5) 112 | self.bottomView!.setY(self.pictureView!.bottom()) 113 | } 114 | 115 | if let votesDict = self.data["votes"] as? NSDictionary 116 | { 117 | let like = votesDict.stringAttributeForKey("up") 118 | let disLike = votesDict.stringAttributeForKey("down") 119 | self.likeLabel!.text = "顶(\(like))" 120 | self.dislikeLabel!.text = "踩(\(disLike))" 121 | } 122 | else 123 | { 124 | self.likeLabel!.text = "顶(0)" 125 | self.dislikeLabel!.text = "踩(0)" 126 | // self.likeLabel!.text = "评论(0)" 127 | }//comments_count 128 | let commentCount = self.data.stringAttributeForKey("comments_count") 129 | self.commentLabel!.text = "评论(\(commentCount))" 130 | 131 | } 132 | 133 | 134 | class func cellHeightByData(_ data:NSDictionary)->CGFloat 135 | { 136 | let width = UIScreen.main.bounds.size.width; 137 | let content = data.stringAttributeForKey("content") 138 | let height = content.stringHeightWith(17,width:width-10*2) 139 | let imgSrc = data.stringAttributeForKey("image") 140 | if imgSrc.isEmpty 141 | { 142 | return 59.0 + height + 40.0 143 | } 144 | return 59.0 + height + 5.0 + 112.0 + 40.0 145 | } 146 | 147 | func imageViewTapped(_ sender:UITapGestureRecognizer) 148 | { 149 | NotificationCenter.default.post(name: Notification.Name(rawValue: "imageViewTapped"), object:self.largeImageURL) 150 | 151 | } 152 | 153 | 154 | 155 | } 156 | -------------------------------------------------------------------------------- /JokeClient-Swift/View/YRJokeCell.xib: -------------------------------------------------------------------------------- 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 | 32 | 39 | 40 | 41 | 42 | 43 | 44 | 51 | 52 | 53 | 54 | 62 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /JokeClient-Swift/View/YRRefreshView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRRefreshView.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-6. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | 13 | protocol YRRefreshViewDelegate 14 | { 15 | // @optional func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) 16 | 17 | func refreshView(_ refreshView:YRRefreshView,didClickButton btn:UIButton) 18 | } 19 | 20 | 21 | class YRRefreshView: UIView { 22 | 23 | @IBOutlet var button:UIButton! 24 | @IBOutlet var indicator: UIActivityIndicatorView! 25 | @IBAction func buttonClicked(_ sender:UIButton) 26 | { 27 | self.delegate.refreshView(self,didClickButton:sender) 28 | } 29 | 30 | 31 | var delegate :YRRefreshViewDelegate! 32 | 33 | 34 | 35 | override func awakeFromNib() 36 | { 37 | super.awakeFromNib() 38 | self.indicator!.isHidden = true 39 | 40 | } 41 | 42 | func startLoading() 43 | { 44 | self.button!.setTitle("", for: UIControlState()) 45 | self.indicator!.isHidden = false 46 | self.indicator!.startAnimating() 47 | } 48 | 49 | func stopLoading() 50 | { 51 | self.button!.setTitle("点击加载更多", for: UIControlState()) 52 | self.indicator!.isHidden = true 53 | self.indicator!.stopAnimating() 54 | } 55 | 56 | /* 57 | // Only override drawRect: if you perform custom drawing. 58 | // An empty implementation adversely affects performance during animation. 59 | override func drawRect(rect: CGRect) 60 | { 61 | // Drawing code 62 | } 63 | */ 64 | 65 | } 66 | -------------------------------------------------------------------------------- /JokeClient-Swift/View/YRRefreshView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /JokeClient-Swift/ViewController/YRAboutViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRAboutViewController.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-5. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YRAboutViewController: UIViewController { 12 | 13 | @IBAction func followMe() 14 | { 15 | let urlString = "http://weibo.com/yangreal" 16 | let url = URL(string: urlString) 17 | UIApplication.shared.openURL(url!) 18 | } 19 | 20 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 21 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 22 | // Custom initialization 23 | } 24 | 25 | 26 | required init?(coder aDecoder: NSCoder) { 27 | fatalError("init(coder:) has not been implemented") 28 | } 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | 33 | // var color = UIColor(red:125/255.0, green:236/255.0,blue:198/255.0,alpha: 1) 34 | // println(color) 35 | 36 | // Do any additional setup after loading the view. 37 | } 38 | 39 | override func didReceiveMemoryWarning() { 40 | super.didReceiveMemoryWarning() 41 | // Dispose of any resources that can be recreated. 42 | } 43 | 44 | 45 | /* 46 | // #pragma mark - Navigation 47 | 48 | // In a storyboard-based application, you will often want to do a little preparation before navigation 49 | override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) { 50 | // Get the new view controller using [segue destinationViewController]. 51 | // Pass the selected object to the new view controller. 52 | } 53 | */ 54 | 55 | } 56 | -------------------------------------------------------------------------------- /JokeClient-Swift/ViewController/YRAboutViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 32 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /JokeClient-Swift/ViewController/YRCommentsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRCommentsViewController.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-7. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YRCommentsViewController: UIViewController,UITableViewDelegate,UITableViewDataSource ,YRRefreshViewDelegate { 12 | 13 | let identifier = "cell" 14 | var jokeType:YRJokeTableViewControllerType = .hotJoke 15 | var tableView:UITableView? 16 | var dataArray = NSMutableArray() 17 | var page :Int = 1 18 | var refreshView:YRRefreshView? 19 | var jokeId:String! 20 | 21 | 22 | 23 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 24 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 25 | // Custom initialization 26 | self.title = "评论" 27 | } 28 | 29 | 30 | 31 | required init?(coder aDecoder: NSCoder) { 32 | fatalError("init(coder:) has not been implemented") 33 | } 34 | 35 | override func viewDidLoad() { 36 | super.viewDidLoad() 37 | setupViews() 38 | loadData() 39 | // Do any additional setup after loading the view. 40 | } 41 | 42 | func setupViews() 43 | { 44 | let width = UIScreen.main.bounds.size.width 45 | let height = self.view.frame.size.height 46 | self.tableView = UITableView(frame:CGRect(x: 0,y: 0,width: width,height: height)) 47 | self.tableView!.delegate = self; 48 | self.tableView!.dataSource = self; 49 | self.tableView!.separatorStyle = UITableViewCellSeparatorStyle.none 50 | let nib = UINib(nibName:"YRCommnentsCell", bundle: nil) 51 | 52 | self.tableView?.register(nib, forCellReuseIdentifier: identifier) 53 | 54 | var arr = Bundle.main.loadNibNamed("YRRefreshView" ,owner: self, options: nil)! 55 | self.refreshView = arr[0] as? YRRefreshView 56 | self.refreshView!.delegate = self 57 | 58 | self.tableView!.tableFooterView = self.refreshView 59 | self.view.addSubview(self.tableView!) 60 | } 61 | 62 | func loadData() 63 | { 64 | let url = "http://m2.qiushibaike.com/article/\(self.jokeId!)/comments?count=20&page=\(self.page)" 65 | self.refreshView!.startLoading() 66 | YRHttpRequest.requestWithURL(url,completionHandler:{ data in 67 | 68 | if data as! NSObject == NSNull() 69 | { 70 | UIView.showAlertView("提示",message:"加载失败") 71 | return 72 | } 73 | 74 | let arr = data["items"] as! NSArray 75 | if arr.count == 0 76 | { 77 | UIView.showAlertView("提示",message:"暂无新评论哦") 78 | self.tableView!.tableFooterView = nil 79 | } 80 | for data in arr 81 | { 82 | self.dataArray.add(data) 83 | } 84 | self.tableView!.reloadData() 85 | self.refreshView!.stopLoading() 86 | self.page += 1 87 | }) 88 | 89 | } 90 | 91 | 92 | func numberOfSections(in tableView: UITableView) -> Int { 93 | return 1; 94 | } 95 | 96 | 97 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 98 | 99 | return self.dataArray.count; 100 | } 101 | 102 | 103 | 104 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 105 | 106 | let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? YRCommnentsCell 107 | let index = indexPath.row 108 | let data = self.dataArray[index] as! NSDictionary 109 | cell!.data = data 110 | return cell! 111 | } 112 | 113 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 114 | { 115 | let index = indexPath.row 116 | let data = self.dataArray[index] as! NSDictionary 117 | return YRCommnentsCell.cellHeightByData(data) 118 | } 119 | // func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) 120 | // { 121 | // var index = indexPath!.row 122 | // var data = self.dataArray[index] as NSDictionary 123 | // println(data) 124 | // } 125 | 126 | func refreshView(_ refreshView:YRRefreshView,didClickButton btn:UIButton) 127 | { 128 | //refreshView.startLoading() 129 | loadData() 130 | } 131 | override func didReceiveMemoryWarning() { 132 | super.didReceiveMemoryWarning() 133 | // Dispose of any resources that can be recreated. 134 | } 135 | 136 | 137 | /* 138 | // #pragma mark - Navigation 139 | 140 | // In a storyboard-based application, you will often want to do a little preparation before navigation 141 | override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) { 142 | // Get the new view controller using [segue destinationViewController]. 143 | // Pass the selected object to the new view controller. 144 | } 145 | */ 146 | 147 | } 148 | -------------------------------------------------------------------------------- /JokeClient-Swift/ViewController/YRImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRImageViewController.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-7. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YRImageViewController: UIViewController { 12 | 13 | var imageURL:String = "" 14 | var imageZoongView:YRImageZoomingView! 15 | 16 | 17 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 18 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 19 | // Custom initialization 20 | self.title = "图片" 21 | } 22 | 23 | required init?(coder aDecoder: NSCoder) { 24 | fatalError("init(coder:) has not been implemented") 25 | } 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | setupViews() 30 | // Do any additional setup after loading the view. 31 | } 32 | 33 | func setupViews() 34 | { 35 | self.imageZoongView = YRImageZoomingView(frame:self.view.frame) 36 | self.imageZoongView.imageURL = self.imageURL 37 | self.view.addSubview(self.imageZoongView) 38 | } 39 | 40 | override func didReceiveMemoryWarning() { 41 | super.didReceiveMemoryWarning() 42 | // Dispose of any resources that can be recreated. 43 | } 44 | 45 | 46 | /* 47 | // #pragma mark - Navigation 48 | 49 | // In a storyboard-based application, you will often want to do a little preparation before navigation 50 | override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) { 51 | // Get the new view controller using [segue destinationViewController]. 52 | // Pass the selected object to the new view controller. 53 | } 54 | */ 55 | 56 | } 57 | -------------------------------------------------------------------------------- /JokeClient-Swift/ViewController/YRJokeTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRJokeTableViewController.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-5. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | enum YRJokeTableViewControllerType : Int { 13 | case hotJoke 14 | case newestJoke 15 | case imageTruth 16 | 17 | } 18 | 19 | class YRJokeTableViewController:UIViewController,YRRefreshViewDelegate,UITableViewDelegate,UITableViewDataSource 20 | 21 | { 22 | 23 | let identifier = "YRJokeCellIdentifier" 24 | var jokeType:YRJokeTableViewControllerType = .hotJoke 25 | var tableView:UITableView? 26 | var dataArray = NSMutableArray() 27 | var cellHeight = NSMutableArray() 28 | var page :Int = 1 29 | var refreshView:YRRefreshView? 30 | 31 | 32 | override func viewDidLoad() 33 | { 34 | super.viewDidLoad() 35 | setupViews() 36 | loadData() 37 | } 38 | 39 | override func viewWillDisappear(_ animated: Bool) 40 | { 41 | super.viewWillDisappear(animated) 42 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "imageViewTapped"), object:nil) 43 | 44 | } 45 | override func viewWillAppear(_ animated: Bool) 46 | { 47 | super.viewWillAppear(animated) 48 | NotificationCenter.default.addObserver(self, selector: #selector(YRJokeTableViewController.imageViewTapped(_:)), name: NSNotification.Name(rawValue: "imageViewTapped"), object: nil) 49 | } 50 | 51 | 52 | 53 | func setupViews() 54 | { 55 | let width = UIScreen.main.bounds.size.width 56 | let height = self.view.frame.size.height 57 | self.tableView = UITableView(frame:CGRect(x: 0,y: 64,width: width,height: height-49-64)) 58 | self.tableView?.delegate = self; 59 | self.tableView?.dataSource = self; 60 | self.tableView?.separatorStyle = UITableViewCellSeparatorStyle.none 61 | let nib = UINib(nibName:"YRJokeCell", bundle: nil) 62 | 63 | self.tableView?.register(nib, forCellReuseIdentifier: identifier) 64 | var arr = Bundle.main.loadNibNamed("YRRefreshView" ,owner: self, options: nil)! 65 | self.refreshView = arr[0] as? YRRefreshView 66 | self.refreshView!.delegate = self 67 | 68 | self.tableView!.tableFooterView = self.refreshView 69 | self.view.addSubview(self.tableView!) 70 | } 71 | 72 | 73 | func loadData() 74 | { 75 | let url = urlString() 76 | self.refreshView!.startLoading() 77 | YRHttpRequest.requestWithURL(url,completionHandler:{ data in 78 | 79 | if data as! NSObject == NSNull() 80 | { 81 | UIView.showAlertView("提示",message:"加载失败") 82 | return 83 | } 84 | 85 | let arr = data["items"] as! NSArray 86 | //println(data) 87 | for data in arr 88 | { 89 | self.cellHeight.add(YRJokeCell.cellHeightByData(data as! NSDictionary)) 90 | self.dataArray.add(data) 91 | } 92 | 93 | self.tableView!.reloadData() 94 | self.refreshView!.stopLoading() 95 | self.page += 1; 96 | }) 97 | } 98 | 99 | 100 | func urlString()->String 101 | { 102 | if jokeType == .hotJoke //最热糗事 103 | { 104 | return "http://m2.qiushibaike.com/article/list/suggest?count=20&page=\(page)" 105 | } 106 | else if jokeType == .newestJoke //最新糗事 107 | { 108 | return "http://m2.qiushibaike.com/article/list/latest?count=20&page=\(page)" 109 | } 110 | else//有图有真相 111 | { 112 | return "http://m2.qiushibaike.com/article/list/imgrank?count=20&page=\(page)" 113 | } 114 | } 115 | 116 | override func didReceiveMemoryWarning() { 117 | super.didReceiveMemoryWarning() 118 | // Dispose of any resources that can be recreated. 119 | } 120 | 121 | func numberOfSections(in tableView: UITableView) -> Int { 122 | // #warning Potentially incomplete method implementation. 123 | // Return the number of sections. 124 | return 1 125 | } 126 | 127 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 128 | { 129 | return self.dataArray.count; 130 | } 131 | 132 | 133 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 134 | { 135 | let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as! YRJokeCell 136 | let index = indexPath.row 137 | let data = self.dataArray[index] as! NSDictionary 138 | cell.data = data 139 | return cell; 140 | } 141 | 142 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 143 | { 144 | let index = indexPath.row 145 | return self.cellHeight[index] as! CGFloat 146 | } 147 | 148 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 149 | { 150 | let index = indexPath.row 151 | let data = self.dataArray[index] as! NSDictionary 152 | let commentsVC = YRCommentsViewController(nibName :nil, bundle: nil) 153 | commentsVC.jokeId = data.stringAttributeForKey("id") 154 | self.navigationController!.pushViewController(commentsVC, animated: true) 155 | } 156 | 157 | func refreshView(_ refreshView:YRRefreshView,didClickButton btn:UIButton) 158 | { 159 | loadData() 160 | } 161 | 162 | func imageViewTapped(_ noti:Notification) 163 | { 164 | 165 | let imageURL = noti.object as! String 166 | let imgVC = YRImageViewController(nibName: nil, bundle: nil) 167 | imgVC.imageURL = imageURL 168 | self.navigationController!.pushViewController(imgVC, animated: true) 169 | 170 | 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /JokeClient-Swift/ViewController/YRMainViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YRMainViewController.swift 3 | // JokeClient-Swift 4 | // 5 | // Created by YANGReal on 14-6-5. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YRMainViewController: UITabBarController { 12 | 13 | var myTabbar :UIView? 14 | var slider :UIView? 15 | let btnBGColor:UIColor = UIColor(red:125/255.0, green:236/255.0,blue:198/255.0,alpha: 1) 16 | let tabBarBGColor:UIColor = UIColor(red:251/255.0, green:173/255.0,blue:69/255.0,alpha: 1) 17 | let titleColor:UIColor = UIColor(red:52/255.0, green:156/255.0,blue:150/255.0,alpha: 1) 18 | 19 | 20 | let itemArray = ["最新","热门","真相","关于"] 21 | 22 | 23 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 24 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 25 | // Custom initialization 26 | self.title = "最新" 27 | } 28 | 29 | required init?(coder aDecoder: NSCoder) { 30 | fatalError("init(coder:) has not been implemented") 31 | } 32 | 33 | override func viewDidLoad() 34 | { 35 | super.viewDidLoad() 36 | setupViews() 37 | initViewControllers() 38 | } 39 | 40 | func setupViews() 41 | { 42 | self.automaticallyAdjustsScrollViewInsets = false 43 | self.view.backgroundColor = UIColor.white 44 | self.tabBar.isHidden = true 45 | let width = UIScreen.main.bounds.size.width; 46 | let height = self.view.frame.size.height 47 | self.myTabbar = UIView(frame: CGRect(x: 0,y: height-49,width: width,height: 49)) 48 | self.myTabbar!.backgroundColor = tabBarBGColor 49 | self.slider = UIView(frame:CGRect(x: 0,y: 0,width: 80,height: 49)) 50 | self.slider!.backgroundColor = UIColor.white//btnBGColor 51 | self.myTabbar!.addSubview(self.slider!) 52 | 53 | self.view.addSubview(self.myTabbar!) 54 | 55 | let count = self.itemArray.count 56 | 57 | for index in 0 ..< count 58 | { 59 | 60 | let btnWidth = (CGFloat)(width/4) 61 | let button = UIButton(type: UIButtonType.custom) 62 | let x = (btnWidth*(CGFloat)(index)); 63 | button.frame = CGRect(x: x, y: 0,width: btnWidth,height: 49) 64 | button.tag = index+100 65 | let title = self.itemArray[index] 66 | button.setTitle(title, for: UIControlState()) 67 | button.setTitleColor(UIColor.white, for: UIControlState()) 68 | button.setTitleColor(tabBarBGColor, for: UIControlState.selected) 69 | 70 | button.addTarget(self, action: #selector(YRMainViewController.tabBarButtonClicked(_:)), for: UIControlEvents.touchUpInside) 71 | self.myTabbar?.addSubview(button) 72 | if index == 0 73 | { 74 | button.isSelected = true 75 | } 76 | } 77 | } 78 | 79 | func initViewControllers() 80 | { 81 | let vc1 = YRJokeTableViewController() 82 | vc1.jokeType = .newestJoke 83 | let vc2 = YRJokeTableViewController() 84 | vc2.jokeType = .hotJoke 85 | let vc3 = YRJokeTableViewController() 86 | vc3.jokeType = .imageTruth 87 | let vc4 = YRAboutViewController(nibName: "YRAboutViewController", bundle: nil) 88 | self.viewControllers = [vc1,vc2,vc3,vc4] 89 | } 90 | 91 | 92 | func tabBarButtonClicked(_ sender:UIButton) 93 | { 94 | let index = sender.tag 95 | 96 | for i in 0 ..< 4 97 | { 98 | let button = self.view.viewWithTag(i+100) as! UIButton 99 | if button.tag == index 100 | { 101 | button.isSelected = true 102 | } 103 | else 104 | { 105 | button.isSelected = false 106 | } 107 | } 108 | let width = UIScreen.main.bounds.size.width; 109 | let btnWidth = (CGFloat)(width/4) 110 | UIView.animate( withDuration: 0.3, 111 | animations:{ 112 | 113 | self.slider!.frame = CGRect(x: CGFloat(index-100)*btnWidth,y: 0,width: btnWidth,height: 49) 114 | 115 | }) 116 | self.title = itemArray[index-100] as String 117 | self.selectedIndex = index-100 118 | } 119 | 120 | 121 | 122 | override func didReceiveMemoryWarning() 123 | { 124 | super.didReceiveMemoryWarning() 125 | 126 | // UIView.animationw 127 | // Dispose of any resources that can be recreated. 128 | } 129 | 130 | 131 | /* 132 | // #pragma mark - Navigation 133 | 134 | // In a storyboard-based application, you will often want to do a little preparation before navigation 135 | override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) { 136 | // Get the new view controller using [segue destinationViewController]. 137 | // Pass the selected object to the new view controller. 138 | } 139 | */ 140 | 141 | } 142 | -------------------------------------------------------------------------------- /JokeClient-Swift/image/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/image/avatar.jpg -------------------------------------------------------------------------------- /JokeClient-Swift/image/me.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/image/me.jpeg -------------------------------------------------------------------------------- /JokeClient-Swift/screenshoot/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/screenshoot/01.png -------------------------------------------------------------------------------- /JokeClient-Swift/screenshoot/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/screenshoot/02.png -------------------------------------------------------------------------------- /JokeClient-Swift/screenshoot/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/screenshoot/03.png -------------------------------------------------------------------------------- /JokeClient-Swift/screenshoot/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/JokeClient-Swift/screenshoot/04.png -------------------------------------------------------------------------------- /JokeClient-SwiftTests/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 | -------------------------------------------------------------------------------- /JokeClient-SwiftTests/JokeClient_SwiftTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JokeClient_SwiftTests.swift 3 | // JokeClient-SwiftTests 4 | // 5 | // Created by YANGReal on 14-6-5. 6 | // Copyright (c) 2014年 YANGReal. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class JokeClient_SwiftTests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | super.tearDown() 21 | } 22 | 23 | func testExample() { 24 | // This is an example of a functional test case. 25 | XCTAssert(true, "Pass") 26 | } 27 | 28 | func testPerformanceExample() { 29 | // This is an example of a performance test case. 30 | self.measure() { 31 | // Put the code you want to measure the time of here. 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JokeClient-Swift 2 | ================ 3 | 1.基于swift 4 | 5 | 2.用糗事百科的API简单做了一个糗百客户端,可以浏览各种段子,浏览搞笑图片,查看精彩评论等. 6 | 7 | 3.本项目仅供学习交流使用,不能用作任何形式的商业用途!内容接口来源于网络上公开的API,如侵犯到相关机构的权益,本人不承担任何后果 8 | 9 | 4.修复一些编译错误 10 | 11 | 5.我的新浪微博http://weibo.com/yangreal 12 | 13 | 14 | 15 | 16 | ![](https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/master/JokeClient-Swift/screenshoot/01.png) 17 | ![](https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/master/JokeClient-Swift/screenshoot/02.png) 18 | ![](https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/master/JokeClient-Swift/screenshoot/03.png) 19 | ![](https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/master/JokeClient-Swift/screenshoot/04.png) 20 | -------------------------------------------------------------------------------- /screenshoot/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/screenshoot/01.png -------------------------------------------------------------------------------- /screenshoot/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/screenshoot/02.png -------------------------------------------------------------------------------- /screenshoot/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/screenshoot/03.png -------------------------------------------------------------------------------- /screenshoot/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YANGReal/JokeClient-Swift/63094b047300af8242232099642f5419d131796a/screenshoot/04.png --------------------------------------------------------------------------------