├── Podfile ├── Podfile.lock ├── Pods ├── Manifest.lock ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── ZeroJian.xcuserdatad │ │ └── xcschemes │ │ ├── Pods.xcscheme │ │ ├── SwiftyJSON.xcscheme │ │ └── xcschememanagement.plist ├── SwiftyJSON │ ├── LICENSE │ ├── README.md │ └── Source │ │ └── SwiftyJSON.swift └── Target Support Files │ ├── Pods │ ├── Info.plist │ ├── Pods-acknowledgements.markdown │ ├── Pods-acknowledgements.plist │ ├── Pods-dummy.m │ ├── Pods-frameworks.sh │ ├── Pods-resources.sh │ ├── Pods-umbrella.h │ ├── Pods.debug.xcconfig │ ├── Pods.modulemap │ └── Pods.release.xcconfig │ └── SwiftyJSON │ ├── Info.plist │ ├── SwiftyJSON-dummy.m │ ├── SwiftyJSON-prefix.pch │ ├── SwiftyJSON-umbrella.h │ ├── SwiftyJSON.modulemap │ └── SwiftyJSON.xcconfig ├── README.md ├── UmbrellaWeather.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── ZeroJian.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── ZeroJian.xcuserdatad │ └── xcschemes │ ├── Background Fetch.xcscheme │ ├── UmbrellaWeather.xcscheme │ └── xcschememanagement.plist ├── UmbrellaWeather.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── ZeroJian.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist └── UmbrellaWeather ├── Animated ├── DimmingPresentationController.swift ├── GradientView.swift └── InteractiveAnimation.swift ├── AppDelegate.swift ├── Base.lproj └── Main.storyboard ├── CityListViewController.swift ├── DataModel ├── City.swift ├── Citys.xml ├── DataModel.swift └── ParserXML.swift ├── HomeViewController.swift ├── Info.plist ├── Interface ├── CityListCell.xib ├── FirstView.xib └── WeekWeatherCell.xib ├── Server ├── DailyResult.swift ├── LocationService.swift ├── ServiceResult.swift ├── UIImageView+WeatherImage.swift └── WeatherResult.swift ├── Sources ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-120.png │ │ ├── Icon-121.png │ │ ├── Icon-180.png │ │ ├── Icon-58.png │ │ ├── Icon-80.png │ │ └── Icon-87.png │ ├── Arrows.imageset │ │ ├── Arrows.pdf │ │ └── Contents.json │ ├── Brand Assets.launchimage │ │ ├── Contents.json │ │ ├── IPhone 6PLus.png │ │ ├── IPhone4.png │ │ ├── IPhone5.png │ │ └── IPhone6.png │ ├── Contents.json │ ├── Detail.imageset │ │ ├── Contents.json │ │ └── Detail.pdf │ ├── DetailColor.imageset │ │ ├── Contents.json │ │ └── DetailColor.pdf │ ├── Launch.imageset │ │ ├── Contents.json │ │ ├── IPhone 6PLus-1.png │ │ └── IPhone6-1.png │ ├── Launch4.imageset │ │ ├── Contents.json │ │ └── IPhone4-1.png │ ├── Launch5.imageset │ │ ├── Contents.json │ │ └── IPhone5-1.png │ ├── Line.imageset │ │ ├── Contents.json │ │ ├── Line@2x.png │ │ └── Line@3x.png │ ├── Loading.imageset │ │ ├── Contents.json │ │ ├── Loading@2x.png │ │ └── Loading@3x.png │ ├── Location.imageset │ │ ├── Contents.json │ │ ├── Location@2x.png │ │ └── Location@3x.png │ ├── Logo.imageset │ │ ├── Contents.json │ │ └── Logo.pdf │ ├── Shape.imageset │ │ ├── Contents.json │ │ ├── Shape@2x.png │ │ └── Shape@3x.png │ └── WeatherImage │ │ ├── Cloudy.imageset │ │ ├── Cloudy.pdf │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Fog.imageset │ │ ├── Contents.json │ │ ├── Fog@2x.png │ │ └── Fog@3x.png │ │ ├── Rain.imageset │ │ ├── Contents.json │ │ └── Rain.pdf │ │ ├── Snow.imageset │ │ ├── Contents.json │ │ └── Snow.pdf │ │ └── Sun.imageset │ │ ├── Contents.json │ │ └── Sun9.pdf ├── DINNextLTPro-Light.otf └── WaterSound.wav ├── SupportTableViewController.swift ├── TimePickerViewController.swift ├── UIcolor+otherColor.swift └── View ├── CityListCell.swift ├── FirstView.swift ├── HeadView.swift ├── HomeView.swift ├── MainScrollView.swift ├── PullView.swift ├── WeatherView.swift ├── WeekWeatherCell.swift └── WeekWeatherCollectionView.swift /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | 3 | pod 'SwiftyJSON', '~> 2.3.2' 4 | use_frameworks! 5 | 6 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SwiftyJSON (2.3.2) 3 | 4 | DEPENDENCIES: 5 | - SwiftyJSON (~> 2.3.2) 6 | 7 | SPEC CHECKSUMS: 8 | SwiftyJSON: 04ccea08915aa0109039157c7974cf0298da292a 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SwiftyJSON (2.3.2) 3 | 4 | DEPENDENCIES: 5 | - SwiftyJSON (~> 2.3.2) 6 | 7 | SPEC CHECKSUMS: 8 | SwiftyJSON: 04ccea08915aa0109039157c7974cf0298da292a 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 44C4F64A26E04DB2A5E41745E111B2B4 /* Pods-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 894E5DA93A9F359521A89826BE6DA777 /* Pods-dummy.m */; }; 11 | 58D67DC97D9F4E0F057A87223A15E8FB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */; }; 12 | 691886E3537DED119660000DC865BCC9 /* SwiftyJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 05CA09B061E193906653AC21FD3A94F1 /* SwiftyJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 832B19BD04D972B79C25420D469F68F7 /* Pods-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BCC458FDD5F692BBB2BFC64BB5701FC /* Pods-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | CE9A434FAFE8158B3A66D6FCB4F507ED /* SwiftyJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B9BBA8F5B33E56C38F5546432F66B7 /* SwiftyJSON-dummy.m */; }; 15 | D18A87B789253DF5E376C49857A964CA /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE506ECE97701EBA44FDBFF401C1A04 /* SwiftyJSON.swift */; }; 16 | F7B9462ED43D98E27777C1C566CAEC0A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | DED02675A046C8DF39C3792995788A89 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = A2BFFC9999EB12DBCF06F86A19A1D5E4; 25 | remoteInfo = SwiftyJSON; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 05CA09B061E193906653AC21FD3A94F1 /* SwiftyJSON-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftyJSON-umbrella.h"; sourceTree = ""; }; 31 | 2BCC458FDD5F692BBB2BFC64BB5701FC /* Pods-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-umbrella.h"; sourceTree = ""; }; 32 | 2E7F7C62EE34D2D271E6E1234A2002B2 /* SwiftyJSON.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftyJSON.xcconfig; sourceTree = ""; }; 33 | 32B9BBA8F5B33E56C38F5546432F66B7 /* SwiftyJSON-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftyJSON-dummy.m"; sourceTree = ""; }; 34 | 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 35 | 4BF91E2E9C3BEBFD7F8F2C550EBC91BB /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 79A9DEDC89FE8336BF5FEDAAF75BF7FC /* Pods.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Pods.modulemap; sourceTree = ""; }; 37 | 87B213035BAC5F75386F62D3C75D2342 /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-acknowledgements.plist"; sourceTree = ""; }; 38 | 894E5DA93A9F359521A89826BE6DA777 /* Pods-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-dummy.m"; sourceTree = ""; }; 39 | 977577C045EDA9D9D1F46E2598D19FC7 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.debug.xcconfig; sourceTree = ""; }; 40 | BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 41 | BBF610E40BDF6E542FA21FF7E5491205 /* SwiftyJSON-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftyJSON-prefix.pch"; sourceTree = ""; }; 42 | BDE506ECE97701EBA44FDBFF401C1A04 /* SwiftyJSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftyJSON.swift; path = Source/SwiftyJSON.swift; sourceTree = ""; }; 43 | C4A9A658C966F6BB111BEDBDEA1F874A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | CBC0F7C552B739C909B650A0F42F7F38 /* Pods-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-resources.sh"; sourceTree = ""; }; 45 | D032A29E584B77AE187E586922267CF5 /* SwiftyJSON.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = SwiftyJSON.modulemap; sourceTree = ""; }; 46 | D0405803033A2A777B8E4DFA0C1800ED /* Pods-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-acknowledgements.markdown"; sourceTree = ""; }; 47 | DA312349A49333542E6F4B36B329960E /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.release.xcconfig; sourceTree = ""; }; 48 | E7E2E816A2F4822B9C40407757AC32FC /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | E7F21354943D9F42A70697D5A5EF72E9 /* Pods-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-frameworks.sh"; sourceTree = ""; }; 50 | E8446514FBAD26C0E18F24A5715AEF67 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 5C07BF63857AF434CC4D1987C7E0A35C /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | F7B9462ED43D98E27777C1C566CAEC0A /* Foundation.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | EE8BDF3F4F4FB025B6184D78EBD0236A /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | 58D67DC97D9F4E0F057A87223A15E8FB /* Foundation.framework in Frameworks */, 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | 70A8E4D3C62B6C203D238581DA091C21 /* SwiftyJSON */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | BDE506ECE97701EBA44FDBFF401C1A04 /* SwiftyJSON.swift */, 77 | 8EC39E1DC11846207722B71AAFE40F98 /* Support Files */, 78 | ); 79 | path = SwiftyJSON; 80 | sourceTree = ""; 81 | }; 82 | 75D98FF52E597A11900E131B6C4E1ADA /* Pods */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | E8446514FBAD26C0E18F24A5715AEF67 /* Info.plist */, 86 | 79A9DEDC89FE8336BF5FEDAAF75BF7FC /* Pods.modulemap */, 87 | D0405803033A2A777B8E4DFA0C1800ED /* Pods-acknowledgements.markdown */, 88 | 87B213035BAC5F75386F62D3C75D2342 /* Pods-acknowledgements.plist */, 89 | 894E5DA93A9F359521A89826BE6DA777 /* Pods-dummy.m */, 90 | E7F21354943D9F42A70697D5A5EF72E9 /* Pods-frameworks.sh */, 91 | CBC0F7C552B739C909B650A0F42F7F38 /* Pods-resources.sh */, 92 | 2BCC458FDD5F692BBB2BFC64BB5701FC /* Pods-umbrella.h */, 93 | 977577C045EDA9D9D1F46E2598D19FC7 /* Pods.debug.xcconfig */, 94 | DA312349A49333542E6F4B36B329960E /* Pods.release.xcconfig */, 95 | ); 96 | name = Pods; 97 | path = "Target Support Files/Pods"; 98 | sourceTree = ""; 99 | }; 100 | 7DB346D0F39D3F0E887471402A8071AB = { 101 | isa = PBXGroup; 102 | children = ( 103 | BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */, 104 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 105 | BD1E3C710F12F4B4C092FC8E2AD22110 /* Pods */, 106 | D90755D1F4FB9E07B7AB8EC8656D2CB2 /* Products */, 107 | B7B80995527643776607AFFA75B91E24 /* Targets Support Files */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | 8EC39E1DC11846207722B71AAFE40F98 /* Support Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | C4A9A658C966F6BB111BEDBDEA1F874A /* Info.plist */, 115 | D032A29E584B77AE187E586922267CF5 /* SwiftyJSON.modulemap */, 116 | 2E7F7C62EE34D2D271E6E1234A2002B2 /* SwiftyJSON.xcconfig */, 117 | 32B9BBA8F5B33E56C38F5546432F66B7 /* SwiftyJSON-dummy.m */, 118 | BBF610E40BDF6E542FA21FF7E5491205 /* SwiftyJSON-prefix.pch */, 119 | 05CA09B061E193906653AC21FD3A94F1 /* SwiftyJSON-umbrella.h */, 120 | ); 121 | name = "Support Files"; 122 | path = "../Target Support Files/SwiftyJSON"; 123 | sourceTree = ""; 124 | }; 125 | B7B80995527643776607AFFA75B91E24 /* Targets Support Files */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 75D98FF52E597A11900E131B6C4E1ADA /* Pods */, 129 | ); 130 | name = "Targets Support Files"; 131 | sourceTree = ""; 132 | }; 133 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | BF6342C8B29F4CEEA088EFF7AB4DE362 /* iOS */, 137 | ); 138 | name = Frameworks; 139 | sourceTree = ""; 140 | }; 141 | BD1E3C710F12F4B4C092FC8E2AD22110 /* Pods */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 70A8E4D3C62B6C203D238581DA091C21 /* SwiftyJSON */, 145 | ); 146 | name = Pods; 147 | sourceTree = ""; 148 | }; 149 | BF6342C8B29F4CEEA088EFF7AB4DE362 /* iOS */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */, 153 | ); 154 | name = iOS; 155 | sourceTree = ""; 156 | }; 157 | D90755D1F4FB9E07B7AB8EC8656D2CB2 /* Products */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 4BF91E2E9C3BEBFD7F8F2C550EBC91BB /* Pods.framework */, 161 | E7E2E816A2F4822B9C40407757AC32FC /* SwiftyJSON.framework */, 162 | ); 163 | name = Products; 164 | sourceTree = ""; 165 | }; 166 | /* End PBXGroup section */ 167 | 168 | /* Begin PBXHeadersBuildPhase section */ 169 | 6ABB360E8394F11C736FE13C2F536B02 /* Headers */ = { 170 | isa = PBXHeadersBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | 691886E3537DED119660000DC865BCC9 /* SwiftyJSON-umbrella.h in Headers */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | 715876937915782C81EF25AA9F36FA29 /* Headers */ = { 178 | isa = PBXHeadersBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 832B19BD04D972B79C25420D469F68F7 /* Pods-umbrella.h in Headers */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXHeadersBuildPhase section */ 186 | 187 | /* Begin PBXNativeTarget section */ 188 | 9BD196C3DED20BF11A665D7D92FCF62F /* Pods */ = { 189 | isa = PBXNativeTarget; 190 | buildConfigurationList = 17C9FB0AF1871D3CD0FC142E1B11F8A2 /* Build configuration list for PBXNativeTarget "Pods" */; 191 | buildPhases = ( 192 | A89D2DC68AA6BA0747B6BE468C884F81 /* Sources */, 193 | EE8BDF3F4F4FB025B6184D78EBD0236A /* Frameworks */, 194 | 715876937915782C81EF25AA9F36FA29 /* Headers */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | B7611EE004F3F6735B42A562A6ED4A44 /* PBXTargetDependency */, 200 | ); 201 | name = Pods; 202 | productName = Pods; 203 | productReference = 4BF91E2E9C3BEBFD7F8F2C550EBC91BB /* Pods.framework */; 204 | productType = "com.apple.product-type.framework"; 205 | }; 206 | A2BFFC9999EB12DBCF06F86A19A1D5E4 /* SwiftyJSON */ = { 207 | isa = PBXNativeTarget; 208 | buildConfigurationList = 2875175DCCB624F6634D9D136CA3FD29 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */; 209 | buildPhases = ( 210 | E4E2BA9FAE9985A76A2433B1DD1ED9FA /* Sources */, 211 | 5C07BF63857AF434CC4D1987C7E0A35C /* Frameworks */, 212 | 6ABB360E8394F11C736FE13C2F536B02 /* Headers */, 213 | ); 214 | buildRules = ( 215 | ); 216 | dependencies = ( 217 | ); 218 | name = SwiftyJSON; 219 | productName = SwiftyJSON; 220 | productReference = E7E2E816A2F4822B9C40407757AC32FC /* SwiftyJSON.framework */; 221 | productType = "com.apple.product-type.framework"; 222 | }; 223 | /* End PBXNativeTarget section */ 224 | 225 | /* Begin PBXProject section */ 226 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 227 | isa = PBXProject; 228 | attributes = { 229 | LastSwiftUpdateCheck = 0700; 230 | LastUpgradeCheck = 0700; 231 | }; 232 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 233 | compatibilityVersion = "Xcode 3.2"; 234 | developmentRegion = English; 235 | hasScannedForEncodings = 0; 236 | knownRegions = ( 237 | en, 238 | ); 239 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 240 | productRefGroup = D90755D1F4FB9E07B7AB8EC8656D2CB2 /* Products */; 241 | projectDirPath = ""; 242 | projectRoot = ""; 243 | targets = ( 244 | 9BD196C3DED20BF11A665D7D92FCF62F /* Pods */, 245 | A2BFFC9999EB12DBCF06F86A19A1D5E4 /* SwiftyJSON */, 246 | ); 247 | }; 248 | /* End PBXProject section */ 249 | 250 | /* Begin PBXSourcesBuildPhase section */ 251 | A89D2DC68AA6BA0747B6BE468C884F81 /* Sources */ = { 252 | isa = PBXSourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | 44C4F64A26E04DB2A5E41745E111B2B4 /* Pods-dummy.m in Sources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | E4E2BA9FAE9985A76A2433B1DD1ED9FA /* Sources */ = { 260 | isa = PBXSourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | CE9A434FAFE8158B3A66D6FCB4F507ED /* SwiftyJSON-dummy.m in Sources */, 264 | D18A87B789253DF5E376C49857A964CA /* SwiftyJSON.swift in Sources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | /* End PBXSourcesBuildPhase section */ 269 | 270 | /* Begin PBXTargetDependency section */ 271 | B7611EE004F3F6735B42A562A6ED4A44 /* PBXTargetDependency */ = { 272 | isa = PBXTargetDependency; 273 | name = SwiftyJSON; 274 | target = A2BFFC9999EB12DBCF06F86A19A1D5E4 /* SwiftyJSON */; 275 | targetProxy = DED02675A046C8DF39C3792995788A89 /* PBXContainerItemProxy */; 276 | }; 277 | /* End PBXTargetDependency section */ 278 | 279 | /* Begin XCBuildConfiguration section */ 280 | 32A42E82E2F1BC57F2F4F2041EFCF509 /* Release */ = { 281 | isa = XCBuildConfiguration; 282 | baseConfigurationReference = DA312349A49333542E6F4B36B329960E /* Pods.release.xcconfig */; 283 | buildSettings = { 284 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 285 | CURRENT_PROJECT_VERSION = 1; 286 | DEFINES_MODULE = YES; 287 | DYLIB_COMPATIBILITY_VERSION = 1; 288 | DYLIB_CURRENT_VERSION = 1; 289 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 290 | ENABLE_STRICT_OBJC_MSGSEND = YES; 291 | INFOPLIST_FILE = "Target Support Files/Pods/Info.plist"; 292 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 293 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 294 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 295 | MACH_O_TYPE = staticlib; 296 | MODULEMAP_FILE = "Target Support Files/Pods/Pods.modulemap"; 297 | MTL_ENABLE_DEBUG_INFO = NO; 298 | OTHER_LDFLAGS = ""; 299 | OTHER_LIBTOOLFLAGS = ""; 300 | PODS_ROOT = "$(SRCROOT)"; 301 | PRODUCT_NAME = Pods; 302 | SDKROOT = iphoneos; 303 | SKIP_INSTALL = YES; 304 | TARGETED_DEVICE_FAMILY = "1,2"; 305 | VERSIONING_SYSTEM = "apple-generic"; 306 | VERSION_INFO_PREFIX = ""; 307 | }; 308 | name = Release; 309 | }; 310 | 97CFFDC80E52D464D3897018EB8A49B2 /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | baseConfigurationReference = 2E7F7C62EE34D2D271E6E1234A2002B2 /* SwiftyJSON.xcconfig */; 313 | buildSettings = { 314 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 315 | CURRENT_PROJECT_VERSION = 1; 316 | DEFINES_MODULE = YES; 317 | DYLIB_COMPATIBILITY_VERSION = 1; 318 | DYLIB_CURRENT_VERSION = 1; 319 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 320 | ENABLE_STRICT_OBJC_MSGSEND = YES; 321 | GCC_PREFIX_HEADER = "Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch"; 322 | INFOPLIST_FILE = "Target Support Files/SwiftyJSON/Info.plist"; 323 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 324 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 325 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 326 | MODULEMAP_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON.modulemap"; 327 | MTL_ENABLE_DEBUG_INFO = YES; 328 | PRODUCT_NAME = SwiftyJSON; 329 | SDKROOT = iphoneos; 330 | SKIP_INSTALL = YES; 331 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 332 | TARGETED_DEVICE_FAMILY = "1,2"; 333 | VERSIONING_SYSTEM = "apple-generic"; 334 | VERSION_INFO_PREFIX = ""; 335 | }; 336 | name = Debug; 337 | }; 338 | A70CDAD61F90AC503C7D04CC22DA2923 /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ALWAYS_SEARCH_USER_PATHS = NO; 342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 343 | CLANG_CXX_LIBRARY = "libc++"; 344 | CLANG_ENABLE_MODULES = YES; 345 | CLANG_ENABLE_OBJC_ARC = YES; 346 | CLANG_WARN_BOOL_CONVERSION = YES; 347 | CLANG_WARN_CONSTANT_CONVERSION = YES; 348 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 349 | CLANG_WARN_EMPTY_BODY = YES; 350 | CLANG_WARN_ENUM_CONVERSION = YES; 351 | CLANG_WARN_INT_CONVERSION = YES; 352 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 353 | CLANG_WARN_UNREACHABLE_CODE = YES; 354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 355 | COPY_PHASE_STRIP = NO; 356 | GCC_C_LANGUAGE_STANDARD = gnu99; 357 | GCC_DYNAMIC_NO_PIC = NO; 358 | GCC_OPTIMIZATION_LEVEL = 0; 359 | GCC_PREPROCESSOR_DEFINITIONS = ( 360 | "DEBUG=1", 361 | "$(inherited)", 362 | ); 363 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 365 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 366 | GCC_WARN_UNDECLARED_SELECTOR = YES; 367 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 368 | GCC_WARN_UNUSED_FUNCTION = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 371 | ONLY_ACTIVE_ARCH = YES; 372 | STRIP_INSTALLED_PRODUCT = NO; 373 | SYMROOT = "${SRCROOT}/../build"; 374 | }; 375 | name = Debug; 376 | }; 377 | CE014A0FB6009D69CD58B065F7528C66 /* Debug */ = { 378 | isa = XCBuildConfiguration; 379 | baseConfigurationReference = 977577C045EDA9D9D1F46E2598D19FC7 /* Pods.debug.xcconfig */; 380 | buildSettings = { 381 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 382 | CURRENT_PROJECT_VERSION = 1; 383 | DEFINES_MODULE = YES; 384 | DYLIB_COMPATIBILITY_VERSION = 1; 385 | DYLIB_CURRENT_VERSION = 1; 386 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 387 | ENABLE_STRICT_OBJC_MSGSEND = YES; 388 | INFOPLIST_FILE = "Target Support Files/Pods/Info.plist"; 389 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 390 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 391 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 392 | MACH_O_TYPE = staticlib; 393 | MODULEMAP_FILE = "Target Support Files/Pods/Pods.modulemap"; 394 | MTL_ENABLE_DEBUG_INFO = YES; 395 | OTHER_LDFLAGS = ""; 396 | OTHER_LIBTOOLFLAGS = ""; 397 | PODS_ROOT = "$(SRCROOT)"; 398 | PRODUCT_NAME = Pods; 399 | SDKROOT = iphoneos; 400 | SKIP_INSTALL = YES; 401 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 402 | TARGETED_DEVICE_FAMILY = "1,2"; 403 | VERSIONING_SYSTEM = "apple-generic"; 404 | VERSION_INFO_PREFIX = ""; 405 | }; 406 | name = Debug; 407 | }; 408 | D1A45F25A023953C2544B61B84AF31FF /* Release */ = { 409 | isa = XCBuildConfiguration; 410 | baseConfigurationReference = 2E7F7C62EE34D2D271E6E1234A2002B2 /* SwiftyJSON.xcconfig */; 411 | buildSettings = { 412 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 413 | CURRENT_PROJECT_VERSION = 1; 414 | DEFINES_MODULE = YES; 415 | DYLIB_COMPATIBILITY_VERSION = 1; 416 | DYLIB_CURRENT_VERSION = 1; 417 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 418 | ENABLE_STRICT_OBJC_MSGSEND = YES; 419 | GCC_PREFIX_HEADER = "Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch"; 420 | INFOPLIST_FILE = "Target Support Files/SwiftyJSON/Info.plist"; 421 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 422 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 423 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 424 | MODULEMAP_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON.modulemap"; 425 | MTL_ENABLE_DEBUG_INFO = NO; 426 | PRODUCT_NAME = SwiftyJSON; 427 | SDKROOT = iphoneos; 428 | SKIP_INSTALL = YES; 429 | TARGETED_DEVICE_FAMILY = "1,2"; 430 | VERSIONING_SYSTEM = "apple-generic"; 431 | VERSION_INFO_PREFIX = ""; 432 | }; 433 | name = Release; 434 | }; 435 | FB45FFD90572718D82AB9092B750F0CA /* Release */ = { 436 | isa = XCBuildConfiguration; 437 | buildSettings = { 438 | ALWAYS_SEARCH_USER_PATHS = NO; 439 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 440 | CLANG_CXX_LIBRARY = "libc++"; 441 | CLANG_ENABLE_MODULES = YES; 442 | CLANG_ENABLE_OBJC_ARC = YES; 443 | CLANG_WARN_BOOL_CONVERSION = YES; 444 | CLANG_WARN_CONSTANT_CONVERSION = YES; 445 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 446 | CLANG_WARN_EMPTY_BODY = YES; 447 | CLANG_WARN_ENUM_CONVERSION = YES; 448 | CLANG_WARN_INT_CONVERSION = YES; 449 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 450 | CLANG_WARN_UNREACHABLE_CODE = YES; 451 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 452 | COPY_PHASE_STRIP = YES; 453 | ENABLE_NS_ASSERTIONS = NO; 454 | GCC_C_LANGUAGE_STANDARD = gnu99; 455 | GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; 456 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 457 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 458 | GCC_WARN_UNDECLARED_SELECTOR = YES; 459 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 460 | GCC_WARN_UNUSED_FUNCTION = YES; 461 | GCC_WARN_UNUSED_VARIABLE = YES; 462 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 463 | STRIP_INSTALLED_PRODUCT = NO; 464 | SYMROOT = "${SRCROOT}/../build"; 465 | VALIDATE_PRODUCT = YES; 466 | }; 467 | name = Release; 468 | }; 469 | /* End XCBuildConfiguration section */ 470 | 471 | /* Begin XCConfigurationList section */ 472 | 17C9FB0AF1871D3CD0FC142E1B11F8A2 /* Build configuration list for PBXNativeTarget "Pods" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | CE014A0FB6009D69CD58B065F7528C66 /* Debug */, 476 | 32A42E82E2F1BC57F2F4F2041EFCF509 /* Release */, 477 | ); 478 | defaultConfigurationIsVisible = 0; 479 | defaultConfigurationName = Release; 480 | }; 481 | 2875175DCCB624F6634D9D136CA3FD29 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */ = { 482 | isa = XCConfigurationList; 483 | buildConfigurations = ( 484 | 97CFFDC80E52D464D3897018EB8A49B2 /* Debug */, 485 | D1A45F25A023953C2544B61B84AF31FF /* Release */, 486 | ); 487 | defaultConfigurationIsVisible = 0; 488 | defaultConfigurationName = Release; 489 | }; 490 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 491 | isa = XCConfigurationList; 492 | buildConfigurations = ( 493 | A70CDAD61F90AC503C7D04CC22DA2923 /* Debug */, 494 | FB45FFD90572718D82AB9092B750F0CA /* Release */, 495 | ); 496 | defaultConfigurationIsVisible = 0; 497 | defaultConfigurationName = Release; 498 | }; 499 | /* End XCConfigurationList section */ 500 | }; 501 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 502 | } 503 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/ZeroJian.xcuserdatad/xcschemes/Pods.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/ZeroJian.xcuserdatad/xcschemes/SwiftyJSON.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/ZeroJian.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Pods.xcscheme 8 | 9 | isShown 10 | 11 | 12 | SwiftyJSON.xcscheme 13 | 14 | isShown 15 | 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 9BD196C3DED20BF11A665D7D92FCF62F 21 | 22 | primary 23 | 24 | 25 | A2BFFC9999EB12DBCF06F86A19A1D5E4 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Pods/SwiftyJSON/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ruoyu Fu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Pods/SwiftyJSON/README.md: -------------------------------------------------------------------------------- 1 | #SwiftyJSON [中文介绍](http://tangplin.github.io/swiftyjson/) 2 | 3 | [![Travis CI](https://travis-ci.org/SwiftyJSON/SwiftyJSON.svg?branch=master)](https://travis-ci.org/SwiftyJSON/SwiftyJSON) 4 | 5 | SwiftyJSON makes it easy to deal with JSON data in Swift. 6 | 7 | 1. [Why is the typical JSON handling in Swift NOT good](#why-is-the-typical-json-handling-in-swift-not-good) 8 | 1. [Requirements](#requirements) 9 | 1. [Integration](#integration) 10 | 1. [Usage](#usage) 11 | - [Initialization](#initialization) 12 | - [Subscript](#subscript) 13 | - [Loop](#loop) 14 | - [Error](#error) 15 | - [Optional getter](#optional-getter) 16 | - [Non-optional getter](#non-optional-getter) 17 | - [Setter](#setter) 18 | - [Raw object](#raw-object) 19 | - [Literal convertibles](#literal-convertibles) 20 | 1. [Work with Alamofire](#work-with-alamofire) 21 | 22 | ##Why is the typical JSON handling in Swift NOT good? 23 | Swift is very strict about types. But although explicit typing is good for saving us from mistakes, it becomes painful when dealing with JSON and other areas that are, by nature, implicit about types. 24 | 25 | Take the Twitter API for example. Say we want to retrieve a user's "name" value of some tweet in Swift (according to Twitter's API https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline). 26 | 27 | The code would look like this: 28 | 29 | ```swift 30 | 31 | if let statusesArray = try? NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]], 32 | let user = statusesArray[0]["user"] as? [String: AnyObject], 33 | let username = user["name"] as? String { 34 | // Finally we got the username 35 | } 36 | 37 | ``` 38 | 39 | It's not good. 40 | 41 | Even if we use optional chaining, it would be messy: 42 | 43 | ```swift 44 | 45 | if let JSONObject = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]], 46 | let username = (JSONObject[0]["user"] as? [String: AnyObject])?["name"] as? String { 47 | // There's our username 48 | } 49 | 50 | ``` 51 | An unreadable mess--for something that should really be simple! 52 | 53 | With SwiftyJSON all you have to do is: 54 | 55 | ```swift 56 | 57 | let json = JSON(data: dataFromNetworking) 58 | if let userName = json[0]["user"]["name"].string { 59 | //Now you got your value 60 | } 61 | 62 | ``` 63 | 64 | And don't worry about the Optional Wrapping thing. It's done for you automatically. 65 | 66 | ```swift 67 | 68 | let json = JSON(data: dataFromNetworking) 69 | if let userName = json[999999]["wrong_key"]["wrong_name"].string { 70 | //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety 71 | } else { 72 | //Print the error 73 | print(json[999999]["wrong_key"]["wrong_name"]) 74 | } 75 | 76 | ``` 77 | 78 | ## Requirements 79 | 80 | - iOS 7.0+ / Mac OS X 10.9+ 81 | - Xcode 7 82 | 83 | ##Integration 84 | 85 | ####CocoaPods (iOS 8+, OS X 10.9+) 86 | You can use [Cocoapods](http://cocoapods.org/) to install `SwiftyJSON`by adding it to your `Podfile`: 87 | ```ruby 88 | platform :ios, '8.0' 89 | use_frameworks! 90 | 91 | target 'MyApp' do 92 | pod 'SwiftyJSON', :git => 'https://github.com/SwiftyJSON/SwiftyJSON.git' 93 | end 94 | ``` 95 | Note that this requires CocoaPods version 36, and your iOS deployment target to be at least 8.0: 96 | 97 | ####Carthage (iOS 8+, OS X 10.9+) 98 | You can use [Carthage](https://github.com/Carthage/Carthage) to install `SwiftyJSON` by adding it to your `Cartfile`: 99 | ``` 100 | github "SwiftyJSON/SwiftyJSON" 101 | ``` 102 | 103 | ####Manually (iOS 7+, OS X 10.9+) 104 | 105 | To use this library in your project manually you may: 106 | 107 | 1. for Projects, just drag SwiftyJSON.swift to the project tree 108 | 2. for Workspaces, include the whole SwiftyJSON.xcodeproj 109 | 110 | ## Usage 111 | 112 | ####Initialization 113 | ```swift 114 | import SwiftyJSON 115 | ``` 116 | ```swift 117 | let json = JSON(data: dataFromNetworking) 118 | ``` 119 | ```swift 120 | let json = JSON(jsonObject) 121 | ``` 122 | ```swift 123 | if let dataFromString = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) { 124 | let json = JSON(data: dataFromString) 125 | } 126 | ``` 127 | 128 | ####Subscript 129 | ```swift 130 | //Getting a double from a JSON Array 131 | let name = json[0].double 132 | ``` 133 | ```swift 134 | //Getting a string from a JSON Dictionary 135 | let name = json["name"].stringValue 136 | ``` 137 | ```swift 138 | //Getting a string using a path to the element 139 | let path = [1,"list",2,"name"] 140 | let name = json[path].string 141 | //Just the same 142 | let name = json[1]["list"][2]["name"].string 143 | //Alternatively 144 | let name = json[1,"list",2,"name"].string 145 | ``` 146 | ```swift 147 | //With a hard way 148 | let name = json[].string 149 | ``` 150 | ```swift 151 | //With a custom way 152 | let keys:[SubscriptType] = [1,"list",2,"name"] 153 | let name = json[keys].string 154 | ``` 155 | ####Loop 156 | ```swift 157 | //If json is .Dictionary 158 | for (key,subJson):(String, JSON) in json { 159 | //Do something you want 160 | } 161 | ``` 162 | *The first element is always a String, even if the JSON is an Array* 163 | ```swift 164 | //If json is .Array 165 | //The `index` is 0.. = json["list"].arrayValue 264 | ``` 265 | ```swift 266 | //If not a Dictionary or nil, return [:] 267 | let user: Dictionary = json["user"].dictionaryValue 268 | ``` 269 | 270 | ####Setter 271 | ```swift 272 | json["name"] = JSON("new-name") 273 | json[0] = JSON(1) 274 | ``` 275 | ```swift 276 | json["id"].int = 1234567890 277 | json["coordinate"].double = 8766.766 278 | json["name"].string = "Jack" 279 | json.arrayObject = [1,2,3,4] 280 | json.dictionary = ["name":"Jack", "age":25] 281 | ``` 282 | 283 | ####Raw object 284 | ```swift 285 | let jsonObject: AnyObject = json.object 286 | ``` 287 | ```swift 288 | if let jsonObject: AnyObject = json.rawValue 289 | ``` 290 | ```swift 291 | //convert the JSON to raw NSData 292 | if let data = json.rawData() { 293 | //Do something you want 294 | } 295 | ``` 296 | ```swift 297 | //convert the JSON to a raw String 298 | if let string = json.rawString() { 299 | //Do something you want 300 | } 301 | ``` 302 | ####Existance 303 | ```swift 304 | //shows you whether value specified in JSON or not 305 | if json["name"].isExists() 306 | ``` 307 | 308 | ####Literal convertibles 309 | For more info about literal convertibles: [Swift Literal Convertibles](http://nshipster.com/swift-literal-convertible/) 310 | ```swift 311 | //StringLiteralConvertible 312 | let json: JSON = "I'm a json" 313 | ``` 314 | ```swift 315 | //IntegerLiteralConvertible 316 | let json: JSON = 12345 317 | ``` 318 | ```swift 319 | //BooleanLiteralConvertible 320 | let json: JSON = true 321 | ``` 322 | ```swift 323 | //FloatLiteralConvertible 324 | let json: JSON = 2.8765 325 | ``` 326 | ```swift 327 | //DictionaryLiteralConvertible 328 | let json: JSON = ["I":"am", "a":"json"] 329 | ``` 330 | ```swift 331 | //ArrayLiteralConvertible 332 | let json: JSON = ["I", "am", "a", "json"] 333 | ``` 334 | ```swift 335 | //NilLiteralConvertible 336 | let json: JSON = nil 337 | ``` 338 | ```swift 339 | //With subscript in array 340 | var json: JSON = [1,2,3] 341 | json[0] = 100 342 | json[1] = 200 343 | json[2] = 300 344 | json[999] = 300 //Don't worry, nothing will happen 345 | ``` 346 | ```swift 347 | //With subscript in dictionary 348 | var json: JSON = ["name": "Jack", "age": 25] 349 | json["name"] = "Mike" 350 | json["age"] = "25" //It's OK to set String 351 | json["address"] = "L.A." // Add the "address": "L.A." in json 352 | ``` 353 | ```swift 354 | //Array & Dictionary 355 | var json: JSON = ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]] 356 | json["list"][3]["what"] = "that" 357 | json["list",3,"what"] = "that" 358 | let path = ["list",3,"what"] 359 | json[path] = "that" 360 | ``` 361 | ##Work with Alamofire 362 | 363 | SwiftyJSON nicely wraps the result of the Alamofire JSON response handler: 364 | ```swift 365 | Alamofire.request(.GET, url).validate().responseJSON { response in 366 | switch response.result { 367 | case .Success: 368 | if let value = response.result.value { 369 | let json = JSON(value) 370 | print("JSON: \(json)") 371 | } 372 | case .Failure(let error): 373 | print(error) 374 | } 375 | } 376 | ``` 377 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## SwiftyJSON 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2014 Ruoyu Fu 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | 28 | Generated by CocoaPods - http://cocoapods.org 29 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2014 Ruoyu Fu 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in 29 | all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 | THE SOFTWARE. 38 | 39 | Title 40 | SwiftyJSON 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - http://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "Pods/SwiftyJSON.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "Pods/SwiftyJSON.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | realpath() { 12 | DIRECTORY="$(cd "${1%/*}" && pwd)" 13 | FILENAME="${1##*/}" 14 | echo "$DIRECTORY/$FILENAME" 15 | } 16 | 17 | install_resource() 18 | { 19 | case $1 in 20 | *.storyboard) 21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 23 | ;; 24 | *.xib) 25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 27 | ;; 28 | *.framework) 29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 33 | ;; 34 | *.xcdatamodel) 35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 37 | ;; 38 | *.xcdatamodeld) 39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 41 | ;; 42 | *.xcmappingmodel) 43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 45 | ;; 46 | *.xcassets) 47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") 48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 49 | ;; 50 | /*) 51 | echo "$1" 52 | echo "$1" >> "$RESOURCES_TO_COPY" 53 | ;; 54 | *) 55 | echo "${PODS_ROOT}/$1" 56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 57 | ;; 58 | esac 59 | } 60 | 61 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 62 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 63 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 64 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 65 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 66 | fi 67 | rm -f "$RESOURCES_TO_COPY" 68 | 69 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 70 | then 71 | case "${TARGETED_DEVICE_FAMILY}" in 72 | 1,2) 73 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 74 | ;; 75 | 1) 76 | TARGET_DEVICE_ARGS="--target-device iphone" 77 | ;; 78 | 2) 79 | TARGET_DEVICE_ARGS="--target-device ipad" 80 | ;; 81 | *) 82 | TARGET_DEVICE_ARGS="--target-device mac" 83 | ;; 84 | esac 85 | 86 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 87 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 88 | while read line; do 89 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 90 | XCASSET_FILES+=("$line") 91 | fi 92 | done <<<"$OTHER_XCASSETS" 93 | 94 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 95 | fi 96 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double PodsVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char PodsVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/SwiftyJSON.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "SwiftyJSON" 6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 7 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods 8 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods { 2 | umbrella header "Pods-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/SwiftyJSON.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "SwiftyJSON" 6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 7 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods 8 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftyJSON/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.3.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftyJSON/SwiftyJSON-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SwiftyJSON : NSObject 3 | @end 4 | @implementation PodsDummy_SwiftyJSON 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftyJSON/SwiftyJSON-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double SwiftyJSONVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char SwiftyJSONVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftyJSON/SwiftyJSON.modulemap: -------------------------------------------------------------------------------- 1 | framework module SwiftyJSON { 2 | umbrella header "SwiftyJSON-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftyJSON/SwiftyJSON.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/SwiftyJSON" "${PODS_ROOT}/Headers/Public" 3 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 4 | PODS_ROOT = ${SRCROOT} 5 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | ![UmbrellaWeather](https://github.com/ZeroJian/ZeroJian.github.io/blob/master/img/SupportLogo.png?raw=true) 3 |
4 | ##UmbrellaWeather 5 | ###The weather app developed in Swift 2,Shelves [AppStore](https://itunes.apple.com/cn/app/umbrellaweather-xia-yu-tong/id1079751819?mt=8) 6 | 7 | 8 | ![launch](https://github.com/ZeroJian/ZeroJian.github.io/blob/master/img/launch.gif?raw=true) 9 | ![addCity](https://github.com/ZeroJian/ZeroJian.github.io/blob/master/img/cityView.gif?raw=true) 10 | ![support](https://github.com/ZeroJian/ZeroJian.github.io/blob/master/img/supportView.gif?raw=true) 11 | 12 | 13 | ###ProjectFeatures 14 | - Use iOS API NSURLSession CoreLocation network requests and location 15 | - stroyboard layout 16 | - 7-day local notifications 17 | - Added a background fetch to refresh data 18 | - NSKeyedArchiver Data persistence 19 | - UIView and layout animation 20 | - Added purchase and jump to AppStore function 21 | 22 | 23 | ###Third party libraries and resources 24 | 25 | Deal with JSON data: [swiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) 26 | 27 | Weather Icons using free resources ,I use Skench adds color [Icons](http://sm-artists.com/?page_id=925) 28 | 29 | ### Matters needing attention 30 | The weather API search does not support other languages, so the APP is only temporary Chinese version ,If you want to use in other regions , location service can work 31 | 32 | use heweather free API service,requests times per day 3000 33 | 34 | If the access limit is exceeded, you can own to register [heweather](http://www.heweather.com) 35 | ###项目特点 36 | - 使用自带 API NSURLSession CoreLocation 网络请求和定位 37 | - 使用纯 storyboard 布局 38 | - 7天本地通知提醒 39 | - 加入了后台刷新更新数据功能 40 | - NSKeyedArchiver 持久化储蓄 41 | - UIView 和 layout 动画 42 | - 加入了内购和跳转到商店功能 43 | 44 | ###使用的第三方库和资源 45 | JSON 解析: [swiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) 46 | 47 | 天气 Icons 使用的免费资源,自己使用 Skench 增加了颜色 [免费 Icons 网址](http://sm-artists.com/?page_id=925) 48 | 49 | ###注意事项 50 | 天气 API 不支持其他国家的城市搜索,如果在其他国家使用,定位城市应该可以工作 51 | 52 | 使用的和风天气免费 API 服务,每天访问次数 3000 53 | 54 | 如果访问超出限制可自行前往注册 [和风天气官网](http://www.heweather.com) -------------------------------------------------------------------------------- /UmbrellaWeather.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 320A8F191C74EC600024F518 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 320A8F1B1C74EC600024F518 /* Main.storyboard */; }; 11 | 320A8F241C7730770024F518 /* CityListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320A8F1E1C7730770024F518 /* CityListCell.swift */; }; 12 | 320A8F251C7730770024F518 /* FirstView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320A8F1F1C7730770024F518 /* FirstView.swift */; }; 13 | 320A8F261C7730770024F518 /* WeatherView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320A8F201C7730770024F518 /* WeatherView.swift */; }; 14 | 320A8F271C7730770024F518 /* PullView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320A8F211C7730770024F518 /* PullView.swift */; }; 15 | 320A8F281C7730770024F518 /* WeekWeatherCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320A8F221C7730770024F518 /* WeekWeatherCell.swift */; }; 16 | 320A8F291C7730770024F518 /* WeekWeatherCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320A8F231C7730770024F518 /* WeekWeatherCollectionView.swift */; }; 17 | 320A8F2D1C7730950024F518 /* CityListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 320A8F2A1C7730950024F518 /* CityListCell.xib */; }; 18 | 320A8F2E1C7730950024F518 /* FirstView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 320A8F2B1C7730950024F518 /* FirstView.xib */; }; 19 | 320A8F2F1C7730950024F518 /* WeekWeatherCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 320A8F2C1C7730950024F518 /* WeekWeatherCell.xib */; }; 20 | 320A8F341C7732960024F518 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 320A8F301C7732960024F518 /* Assets.xcassets */; }; 21 | 320A8F351C7732960024F518 /* DINNextLTPro-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 320A8F311C7732960024F518 /* DINNextLTPro-Light.otf */; }; 22 | 320A8F371C7732960024F518 /* WaterSound.wav in Resources */ = {isa = PBXBuildFile; fileRef = 320A8F331C7732960024F518 /* WaterSound.wav */; }; 23 | 3215992B1C3E35CC00F68FA4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3215992A1C3E35CC00F68FA4 /* AppDelegate.swift */; }; 24 | 3215994C1C3E371300F68FA4 /* ServiceResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3215994B1C3E371300F68FA4 /* ServiceResult.swift */; }; 25 | 3215994E1C3E371900F68FA4 /* WeatherResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3215994D1C3E371900F68FA4 /* WeatherResult.swift */; }; 26 | 321599501C3E371E00F68FA4 /* DailyResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3215994F1C3E371E00F68FA4 /* DailyResult.swift */; }; 27 | 321599541C3E372800F68FA4 /* LocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 321599531C3E372800F68FA4 /* LocationService.swift */; }; 28 | 321599581C3E376C00F68FA4 /* DimmingPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 321599571C3E376C00F68FA4 /* DimmingPresentationController.swift */; }; 29 | 3215995A1C3E377200F68FA4 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 321599591C3E377200F68FA4 /* GradientView.swift */; }; 30 | 3215995E1C3E378F00F68FA4 /* City.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3215995D1C3E378F00F68FA4 /* City.swift */; }; 31 | 321599601C3E379400F68FA4 /* ParserXML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3215995F1C3E379400F68FA4 /* ParserXML.swift */; }; 32 | 321599621C3E379900F68FA4 /* Citys.xml in Resources */ = {isa = PBXBuildFile; fileRef = 321599611C3E379900F68FA4 /* Citys.xml */; }; 33 | 321599681C3E3B8E00F68FA4 /* DataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 321599671C3E3B8E00F68FA4 /* DataModel.swift */; }; 34 | 3215996E1C3E3C1300F68FA4 /* TimePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3215996D1C3E3C1300F68FA4 /* TimePickerViewController.swift */; }; 35 | 32B94B481C55E0DD006EE4BB /* UIImageView+WeatherImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B94B471C55E0DD006EE4BB /* UIImageView+WeatherImage.swift */; }; 36 | 32C8B58A1CD9F85500757CDD /* MainScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C8B5891CD9F85500757CDD /* MainScrollView.swift */; }; 37 | 32C8B58C1CDA0D8F00757CDD /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C8B58B1CDA0D8F00757CDD /* HomeView.swift */; }; 38 | 32C8B58E1CDA0DD700757CDD /* HeadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C8B58D1CDA0DD700757CDD /* HeadView.swift */; }; 39 | 32C8B5901CDA2AAE00757CDD /* UIcolor+otherColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C8B58F1CDA2AAE00757CDD /* UIcolor+otherColor.swift */; }; 40 | 32D1539D1C50FB05000A4959 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D1539C1C50FB05000A4959 /* HomeViewController.swift */; }; 41 | 32F211B81C5358DE00B80498 /* CityListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F211B71C5358DE00B80498 /* CityListViewController.swift */; }; 42 | 32F211BC1C5361E600B80498 /* SupportTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F211BB1C5361E600B80498 /* SupportTableViewController.swift */; }; 43 | 32F211C01C53EFC900B80498 /* InteractiveAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F211BF1C53EFC900B80498 /* InteractiveAnimation.swift */; }; 44 | A70F355714621E5F27718690 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC37378A4ED40604FEEFD272 /* Pods.framework */; }; 45 | /* End PBXBuildFile section */ 46 | 47 | /* Begin PBXFileReference section */ 48 | 320A8F1A1C74EC600024F518 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 320A8F1E1C7730770024F518 /* CityListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CityListCell.swift; sourceTree = ""; }; 50 | 320A8F1F1C7730770024F518 /* FirstView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstView.swift; sourceTree = ""; }; 51 | 320A8F201C7730770024F518 /* WeatherView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeatherView.swift; sourceTree = ""; }; 52 | 320A8F211C7730770024F518 /* PullView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PullView.swift; sourceTree = ""; }; 53 | 320A8F221C7730770024F518 /* WeekWeatherCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeekWeatherCell.swift; sourceTree = ""; }; 54 | 320A8F231C7730770024F518 /* WeekWeatherCollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeekWeatherCollectionView.swift; sourceTree = ""; }; 55 | 320A8F2A1C7730950024F518 /* CityListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CityListCell.xib; sourceTree = ""; }; 56 | 320A8F2B1C7730950024F518 /* FirstView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FirstView.xib; sourceTree = ""; }; 57 | 320A8F2C1C7730950024F518 /* WeekWeatherCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WeekWeatherCell.xib; sourceTree = ""; }; 58 | 320A8F301C7732960024F518 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 59 | 320A8F311C7732960024F518 /* DINNextLTPro-Light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "DINNextLTPro-Light.otf"; sourceTree = ""; }; 60 | 320A8F331C7732960024F518 /* WaterSound.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = WaterSound.wav; sourceTree = ""; }; 61 | 320A8F381C77330D0024F518 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | 321599271C3E35CC00F68FA4 /* UmbrellaWeather.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UmbrellaWeather.app; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 3215992A1C3E35CC00F68FA4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AppDelegate.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 64 | 3215994B1C3E371300F68FA4 /* ServiceResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ServiceResult.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 65 | 3215994D1C3E371900F68FA4 /* WeatherResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WeatherResult.swift; path = ../Server/WeatherResult.swift; sourceTree = ""; }; 66 | 3215994F1C3E371E00F68FA4 /* DailyResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DailyResult.swift; path = ../Server/DailyResult.swift; sourceTree = ""; }; 67 | 321599531C3E372800F68FA4 /* LocationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = LocationService.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 68 | 321599571C3E376C00F68FA4 /* DimmingPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DimmingPresentationController.swift; sourceTree = ""; }; 69 | 321599591C3E377200F68FA4 /* GradientView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; 70 | 3215995D1C3E378F00F68FA4 /* City.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = City.swift; sourceTree = ""; }; 71 | 3215995F1C3E379400F68FA4 /* ParserXML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParserXML.swift; sourceTree = ""; }; 72 | 321599611C3E379900F68FA4 /* Citys.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Citys.xml; sourceTree = ""; }; 73 | 321599671C3E3B8E00F68FA4 /* DataModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataModel.swift; sourceTree = ""; }; 74 | 3215996D1C3E3C1300F68FA4 /* TimePickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimePickerViewController.swift; sourceTree = ""; }; 75 | 32B94B471C55E0DD006EE4BB /* UIImageView+WeatherImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+WeatherImage.swift"; sourceTree = ""; }; 76 | 32C8B5891CD9F85500757CDD /* MainScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainScrollView.swift; sourceTree = ""; }; 77 | 32C8B58B1CDA0D8F00757CDD /* HomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; 78 | 32C8B58D1CDA0DD700757CDD /* HeadView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadView.swift; sourceTree = ""; }; 79 | 32C8B58F1CDA2AAE00757CDD /* UIcolor+otherColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIcolor+otherColor.swift"; sourceTree = ""; }; 80 | 32D1539C1C50FB05000A4959 /* HomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = HomeViewController.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 81 | 32F211B71C5358DE00B80498 /* CityListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CityListViewController.swift; sourceTree = ""; }; 82 | 32F211BB1C5361E600B80498 /* SupportTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SupportTableViewController.swift; sourceTree = ""; }; 83 | 32F211BF1C53EFC900B80498 /* InteractiveAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InteractiveAnimation.swift; sourceTree = ""; }; 84 | E76A1C10B9FEC9B6E129190B /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 85 | EC37378A4ED40604FEEFD272 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 86 | FF206AD08664F268F593CBC0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 87 | /* End PBXFileReference section */ 88 | 89 | /* Begin PBXFrameworksBuildPhase section */ 90 | 321599241C3E35CC00F68FA4 /* Frameworks */ = { 91 | isa = PBXFrameworksBuildPhase; 92 | buildActionMask = 2147483647; 93 | files = ( 94 | A70F355714621E5F27718690 /* Pods.framework in Frameworks */, 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | /* End PBXFrameworksBuildPhase section */ 99 | 100 | /* Begin PBXGroup section */ 101 | 3215991E1C3E35CC00F68FA4 = { 102 | isa = PBXGroup; 103 | children = ( 104 | 321599291C3E35CC00F68FA4 /* UmbrellaWeather */, 105 | 321599281C3E35CC00F68FA4 /* Products */, 106 | 7EE8AE5283A59FF782005F6F /* Pods */, 107 | E3678054E28D90CF25381A9E /* Frameworks */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | 321599281C3E35CC00F68FA4 /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 321599271C3E35CC00F68FA4 /* UmbrellaWeather.app */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | 321599291C3E35CC00F68FA4 /* UmbrellaWeather */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 3215992A1C3E35CC00F68FA4 /* AppDelegate.swift */, 123 | 32D1539C1C50FB05000A4959 /* HomeViewController.swift */, 124 | 3215996D1C3E3C1300F68FA4 /* TimePickerViewController.swift */, 125 | 32F211BB1C5361E600B80498 /* SupportTableViewController.swift */, 126 | 32F211B71C5358DE00B80498 /* CityListViewController.swift */, 127 | 32C8B58F1CDA2AAE00757CDD /* UIcolor+otherColor.swift */, 128 | 3221724B1C5B8854008EBA1D /* View */, 129 | 321599421C3E36BD00F68FA4 /* Animated */, 130 | 321599411C3E36A700F68FA4 /* Service */, 131 | 321599401C3E368C00F68FA4 /* DataModel */, 132 | 3221724D1C5B89D4008EBA1D /* Interface */, 133 | 3221724C1C5B8960008EBA1D /* Sources */, 134 | 320A8F381C77330D0024F518 /* Info.plist */, 135 | ); 136 | path = UmbrellaWeather; 137 | sourceTree = ""; 138 | }; 139 | 321599401C3E368C00F68FA4 /* DataModel */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 321599671C3E3B8E00F68FA4 /* DataModel.swift */, 143 | 3215994D1C3E371900F68FA4 /* WeatherResult.swift */, 144 | 3215994F1C3E371E00F68FA4 /* DailyResult.swift */, 145 | 3215995D1C3E378F00F68FA4 /* City.swift */, 146 | 3215995F1C3E379400F68FA4 /* ParserXML.swift */, 147 | 321599611C3E379900F68FA4 /* Citys.xml */, 148 | ); 149 | path = DataModel; 150 | sourceTree = ""; 151 | }; 152 | 321599411C3E36A700F68FA4 /* Service */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 3215994B1C3E371300F68FA4 /* ServiceResult.swift */, 156 | 321599531C3E372800F68FA4 /* LocationService.swift */, 157 | 32B94B471C55E0DD006EE4BB /* UIImageView+WeatherImage.swift */, 158 | ); 159 | name = Service; 160 | path = Server; 161 | sourceTree = ""; 162 | }; 163 | 321599421C3E36BD00F68FA4 /* Animated */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 321599571C3E376C00F68FA4 /* DimmingPresentationController.swift */, 167 | 321599591C3E377200F68FA4 /* GradientView.swift */, 168 | 32F211BF1C53EFC900B80498 /* InteractiveAnimation.swift */, 169 | ); 170 | path = Animated; 171 | sourceTree = ""; 172 | }; 173 | 3221724B1C5B8854008EBA1D /* View */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 32C8B58B1CDA0D8F00757CDD /* HomeView.swift */, 177 | 32C8B58D1CDA0DD700757CDD /* HeadView.swift */, 178 | 32C8B5891CD9F85500757CDD /* MainScrollView.swift */, 179 | 320A8F211C7730770024F518 /* PullView.swift */, 180 | 320A8F201C7730770024F518 /* WeatherView.swift */, 181 | 320A8F1F1C7730770024F518 /* FirstView.swift */, 182 | 320A8F1E1C7730770024F518 /* CityListCell.swift */, 183 | 320A8F221C7730770024F518 /* WeekWeatherCell.swift */, 184 | 320A8F231C7730770024F518 /* WeekWeatherCollectionView.swift */, 185 | ); 186 | path = View; 187 | sourceTree = ""; 188 | }; 189 | 3221724C1C5B8960008EBA1D /* Sources */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 320A8F301C7732960024F518 /* Assets.xcassets */, 193 | 320A8F311C7732960024F518 /* DINNextLTPro-Light.otf */, 194 | 320A8F331C7732960024F518 /* WaterSound.wav */, 195 | ); 196 | path = Sources; 197 | sourceTree = ""; 198 | }; 199 | 3221724D1C5B89D4008EBA1D /* Interface */ = { 200 | isa = PBXGroup; 201 | children = ( 202 | 320A8F1B1C74EC600024F518 /* Main.storyboard */, 203 | 320A8F2A1C7730950024F518 /* CityListCell.xib */, 204 | 320A8F2B1C7730950024F518 /* FirstView.xib */, 205 | 320A8F2C1C7730950024F518 /* WeekWeatherCell.xib */, 206 | ); 207 | path = Interface; 208 | sourceTree = ""; 209 | }; 210 | 7EE8AE5283A59FF782005F6F /* Pods */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | FF206AD08664F268F593CBC0 /* Pods.debug.xcconfig */, 214 | E76A1C10B9FEC9B6E129190B /* Pods.release.xcconfig */, 215 | ); 216 | name = Pods; 217 | sourceTree = ""; 218 | }; 219 | E3678054E28D90CF25381A9E /* Frameworks */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | EC37378A4ED40604FEEFD272 /* Pods.framework */, 223 | ); 224 | name = Frameworks; 225 | sourceTree = ""; 226 | }; 227 | /* End PBXGroup section */ 228 | 229 | /* Begin PBXNativeTarget section */ 230 | 321599261C3E35CC00F68FA4 /* UmbrellaWeather */ = { 231 | isa = PBXNativeTarget; 232 | buildConfigurationList = 321599391C3E35CC00F68FA4 /* Build configuration list for PBXNativeTarget "UmbrellaWeather" */; 233 | buildPhases = ( 234 | 78B24D53E7F9E0A23C8E8425 /* Check Pods Manifest.lock */, 235 | 321599231C3E35CC00F68FA4 /* Sources */, 236 | 321599241C3E35CC00F68FA4 /* Frameworks */, 237 | 321599251C3E35CC00F68FA4 /* Resources */, 238 | EA3A16AFAEF3D099302BE743 /* Embed Pods Frameworks */, 239 | 4139B63036010023A30CB969 /* Copy Pods Resources */, 240 | ); 241 | buildRules = ( 242 | ); 243 | dependencies = ( 244 | ); 245 | name = UmbrellaWeather; 246 | productName = UmbrellaWeather; 247 | productReference = 321599271C3E35CC00F68FA4 /* UmbrellaWeather.app */; 248 | productType = "com.apple.product-type.application"; 249 | }; 250 | /* End PBXNativeTarget section */ 251 | 252 | /* Begin PBXProject section */ 253 | 3215991F1C3E35CC00F68FA4 /* Project object */ = { 254 | isa = PBXProject; 255 | attributes = { 256 | LastSwiftUpdateCheck = 0720; 257 | LastUpgradeCheck = 0720; 258 | ORGANIZATIONNAME = ZeroJian; 259 | TargetAttributes = { 260 | 321599261C3E35CC00F68FA4 = { 261 | CreatedOnToolsVersion = 7.2; 262 | SystemCapabilities = { 263 | com.apple.BackgroundModes = { 264 | enabled = 1; 265 | }; 266 | com.apple.InterAppAudio = { 267 | enabled = 0; 268 | }; 269 | com.apple.Push = { 270 | enabled = 0; 271 | }; 272 | }; 273 | }; 274 | }; 275 | }; 276 | buildConfigurationList = 321599221C3E35CC00F68FA4 /* Build configuration list for PBXProject "UmbrellaWeather" */; 277 | compatibilityVersion = "Xcode 3.2"; 278 | developmentRegion = English; 279 | hasScannedForEncodings = 0; 280 | knownRegions = ( 281 | en, 282 | Base, 283 | ); 284 | mainGroup = 3215991E1C3E35CC00F68FA4; 285 | productRefGroup = 321599281C3E35CC00F68FA4 /* Products */; 286 | projectDirPath = ""; 287 | projectRoot = ""; 288 | targets = ( 289 | 321599261C3E35CC00F68FA4 /* UmbrellaWeather */, 290 | ); 291 | }; 292 | /* End PBXProject section */ 293 | 294 | /* Begin PBXResourcesBuildPhase section */ 295 | 321599251C3E35CC00F68FA4 /* Resources */ = { 296 | isa = PBXResourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | 320A8F2D1C7730950024F518 /* CityListCell.xib in Resources */, 300 | 320A8F371C7732960024F518 /* WaterSound.wav in Resources */, 301 | 320A8F191C74EC600024F518 /* Main.storyboard in Resources */, 302 | 321599621C3E379900F68FA4 /* Citys.xml in Resources */, 303 | 320A8F2F1C7730950024F518 /* WeekWeatherCell.xib in Resources */, 304 | 320A8F341C7732960024F518 /* Assets.xcassets in Resources */, 305 | 320A8F2E1C7730950024F518 /* FirstView.xib in Resources */, 306 | 320A8F351C7732960024F518 /* DINNextLTPro-Light.otf in Resources */, 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | /* End PBXResourcesBuildPhase section */ 311 | 312 | /* Begin PBXShellScriptBuildPhase section */ 313 | 4139B63036010023A30CB969 /* Copy Pods Resources */ = { 314 | isa = PBXShellScriptBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | ); 318 | inputPaths = ( 319 | ); 320 | name = "Copy Pods Resources"; 321 | outputPaths = ( 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | shellPath = /bin/sh; 325 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 326 | showEnvVarsInLog = 0; 327 | }; 328 | 78B24D53E7F9E0A23C8E8425 /* Check Pods Manifest.lock */ = { 329 | isa = PBXShellScriptBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | ); 333 | inputPaths = ( 334 | ); 335 | name = "Check Pods Manifest.lock"; 336 | outputPaths = ( 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | shellPath = /bin/sh; 340 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 341 | showEnvVarsInLog = 0; 342 | }; 343 | EA3A16AFAEF3D099302BE743 /* Embed Pods Frameworks */ = { 344 | isa = PBXShellScriptBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | ); 348 | inputPaths = ( 349 | ); 350 | name = "Embed Pods Frameworks"; 351 | outputPaths = ( 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | shellPath = /bin/sh; 355 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; 356 | showEnvVarsInLog = 0; 357 | }; 358 | /* End PBXShellScriptBuildPhase section */ 359 | 360 | /* Begin PBXSourcesBuildPhase section */ 361 | 321599231C3E35CC00F68FA4 /* Sources */ = { 362 | isa = PBXSourcesBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | 320A8F291C7730770024F518 /* WeekWeatherCollectionView.swift in Sources */, 366 | 320A8F261C7730770024F518 /* WeatherView.swift in Sources */, 367 | 3215992B1C3E35CC00F68FA4 /* AppDelegate.swift in Sources */, 368 | 320A8F241C7730770024F518 /* CityListCell.swift in Sources */, 369 | 32C8B58A1CD9F85500757CDD /* MainScrollView.swift in Sources */, 370 | 321599541C3E372800F68FA4 /* LocationService.swift in Sources */, 371 | 3215994C1C3E371300F68FA4 /* ServiceResult.swift in Sources */, 372 | 320A8F251C7730770024F518 /* FirstView.swift in Sources */, 373 | 32F211B81C5358DE00B80498 /* CityListViewController.swift in Sources */, 374 | 32F211C01C53EFC900B80498 /* InteractiveAnimation.swift in Sources */, 375 | 32C8B58E1CDA0DD700757CDD /* HeadView.swift in Sources */, 376 | 32F211BC1C5361E600B80498 /* SupportTableViewController.swift in Sources */, 377 | 320A8F281C7730770024F518 /* WeekWeatherCell.swift in Sources */, 378 | 32D1539D1C50FB05000A4959 /* HomeViewController.swift in Sources */, 379 | 32B94B481C55E0DD006EE4BB /* UIImageView+WeatherImage.swift in Sources */, 380 | 321599601C3E379400F68FA4 /* ParserXML.swift in Sources */, 381 | 3215994E1C3E371900F68FA4 /* WeatherResult.swift in Sources */, 382 | 320A8F271C7730770024F518 /* PullView.swift in Sources */, 383 | 32C8B5901CDA2AAE00757CDD /* UIcolor+otherColor.swift in Sources */, 384 | 321599501C3E371E00F68FA4 /* DailyResult.swift in Sources */, 385 | 3215995E1C3E378F00F68FA4 /* City.swift in Sources */, 386 | 3215996E1C3E3C1300F68FA4 /* TimePickerViewController.swift in Sources */, 387 | 3215995A1C3E377200F68FA4 /* GradientView.swift in Sources */, 388 | 32C8B58C1CDA0D8F00757CDD /* HomeView.swift in Sources */, 389 | 321599581C3E376C00F68FA4 /* DimmingPresentationController.swift in Sources */, 390 | 321599681C3E3B8E00F68FA4 /* DataModel.swift in Sources */, 391 | ); 392 | runOnlyForDeploymentPostprocessing = 0; 393 | }; 394 | /* End PBXSourcesBuildPhase section */ 395 | 396 | /* Begin PBXVariantGroup section */ 397 | 320A8F1B1C74EC600024F518 /* Main.storyboard */ = { 398 | isa = PBXVariantGroup; 399 | children = ( 400 | 320A8F1A1C74EC600024F518 /* Base */, 401 | ); 402 | name = Main.storyboard; 403 | path = ..; 404 | sourceTree = ""; 405 | }; 406 | /* End PBXVariantGroup section */ 407 | 408 | /* Begin XCBuildConfiguration section */ 409 | 321599371C3E35CC00F68FA4 /* Debug */ = { 410 | isa = XCBuildConfiguration; 411 | buildSettings = { 412 | ALWAYS_SEARCH_USER_PATHS = NO; 413 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 414 | CLANG_CXX_LIBRARY = "libc++"; 415 | CLANG_ENABLE_MODULES = YES; 416 | CLANG_ENABLE_OBJC_ARC = YES; 417 | CLANG_WARN_BOOL_CONVERSION = YES; 418 | CLANG_WARN_CONSTANT_CONVERSION = YES; 419 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 420 | CLANG_WARN_EMPTY_BODY = YES; 421 | CLANG_WARN_ENUM_CONVERSION = YES; 422 | CLANG_WARN_INT_CONVERSION = YES; 423 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 424 | CLANG_WARN_UNREACHABLE_CODE = YES; 425 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 426 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 427 | COPY_PHASE_STRIP = NO; 428 | DEBUG_INFORMATION_FORMAT = dwarf; 429 | ENABLE_STRICT_OBJC_MSGSEND = YES; 430 | ENABLE_TESTABILITY = YES; 431 | GCC_C_LANGUAGE_STANDARD = gnu99; 432 | GCC_DYNAMIC_NO_PIC = NO; 433 | GCC_NO_COMMON_BLOCKS = YES; 434 | GCC_OPTIMIZATION_LEVEL = 0; 435 | GCC_PREPROCESSOR_DEFINITIONS = ( 436 | "DEBUG=1", 437 | "$(inherited)", 438 | ); 439 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 441 | GCC_WARN_UNDECLARED_SELECTOR = YES; 442 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 443 | GCC_WARN_UNUSED_FUNCTION = YES; 444 | GCC_WARN_UNUSED_VARIABLE = YES; 445 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 446 | MTL_ENABLE_DEBUG_INFO = YES; 447 | ONLY_ACTIVE_ARCH = YES; 448 | SDKROOT = iphoneos; 449 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 450 | }; 451 | name = Debug; 452 | }; 453 | 321599381C3E35CC00F68FA4 /* Release */ = { 454 | isa = XCBuildConfiguration; 455 | buildSettings = { 456 | ALWAYS_SEARCH_USER_PATHS = NO; 457 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 458 | CLANG_CXX_LIBRARY = "libc++"; 459 | CLANG_ENABLE_MODULES = YES; 460 | CLANG_ENABLE_OBJC_ARC = YES; 461 | CLANG_WARN_BOOL_CONVERSION = YES; 462 | CLANG_WARN_CONSTANT_CONVERSION = YES; 463 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 464 | CLANG_WARN_EMPTY_BODY = YES; 465 | CLANG_WARN_ENUM_CONVERSION = YES; 466 | CLANG_WARN_INT_CONVERSION = YES; 467 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 468 | CLANG_WARN_UNREACHABLE_CODE = YES; 469 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 470 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 471 | COPY_PHASE_STRIP = NO; 472 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 473 | ENABLE_NS_ASSERTIONS = NO; 474 | ENABLE_STRICT_OBJC_MSGSEND = YES; 475 | GCC_C_LANGUAGE_STANDARD = gnu99; 476 | GCC_NO_COMMON_BLOCKS = YES; 477 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 478 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 479 | GCC_WARN_UNDECLARED_SELECTOR = YES; 480 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 481 | GCC_WARN_UNUSED_FUNCTION = YES; 482 | GCC_WARN_UNUSED_VARIABLE = YES; 483 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 484 | MTL_ENABLE_DEBUG_INFO = NO; 485 | SDKROOT = iphoneos; 486 | VALIDATE_PRODUCT = YES; 487 | }; 488 | name = Release; 489 | }; 490 | 3215993A1C3E35CC00F68FA4 /* Debug */ = { 491 | isa = XCBuildConfiguration; 492 | baseConfigurationReference = FF206AD08664F268F593CBC0 /* Pods.debug.xcconfig */; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; 496 | CLANG_ENABLE_MODULES = YES; 497 | CODE_SIGN_IDENTITY = "iPhone Developer"; 498 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 499 | INFOPLIST_FILE = UmbrellaWeather/Info.plist; 500 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 501 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 502 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 503 | PRODUCT_BUNDLE_IDENTIFIER = com.zerojian.UmbWeather; 504 | PRODUCT_NAME = "$(TARGET_NAME)"; 505 | PROVISIONING_PROFILE = ""; 506 | SWIFT_OBJC_BRIDGING_HEADER = ""; 507 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 508 | TARGETED_DEVICE_FAMILY = 1; 509 | }; 510 | name = Debug; 511 | }; 512 | 3215993B1C3E35CC00F68FA4 /* Release */ = { 513 | isa = XCBuildConfiguration; 514 | baseConfigurationReference = E76A1C10B9FEC9B6E129190B /* Pods.release.xcconfig */; 515 | buildSettings = { 516 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 517 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; 518 | CLANG_ENABLE_MODULES = YES; 519 | CODE_SIGN_IDENTITY = "iPhone Developer"; 520 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 521 | INFOPLIST_FILE = UmbrellaWeather/Info.plist; 522 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 523 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 524 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 525 | PRODUCT_BUNDLE_IDENTIFIER = com.zerojian.UmbWeather; 526 | PRODUCT_NAME = "$(TARGET_NAME)"; 527 | PROVISIONING_PROFILE = ""; 528 | SWIFT_OBJC_BRIDGING_HEADER = ""; 529 | TARGETED_DEVICE_FAMILY = 1; 530 | }; 531 | name = Release; 532 | }; 533 | /* End XCBuildConfiguration section */ 534 | 535 | /* Begin XCConfigurationList section */ 536 | 321599221C3E35CC00F68FA4 /* Build configuration list for PBXProject "UmbrellaWeather" */ = { 537 | isa = XCConfigurationList; 538 | buildConfigurations = ( 539 | 321599371C3E35CC00F68FA4 /* Debug */, 540 | 321599381C3E35CC00F68FA4 /* Release */, 541 | ); 542 | defaultConfigurationIsVisible = 0; 543 | defaultConfigurationName = Release; 544 | }; 545 | 321599391C3E35CC00F68FA4 /* Build configuration list for PBXNativeTarget "UmbrellaWeather" */ = { 546 | isa = XCConfigurationList; 547 | buildConfigurations = ( 548 | 3215993A1C3E35CC00F68FA4 /* Debug */, 549 | 3215993B1C3E35CC00F68FA4 /* Release */, 550 | ); 551 | defaultConfigurationIsVisible = 0; 552 | defaultConfigurationName = Release; 553 | }; 554 | /* End XCConfigurationList section */ 555 | }; 556 | rootObject = 3215991F1C3E35CC00F68FA4 /* Project object */; 557 | } 558 | -------------------------------------------------------------------------------- /UmbrellaWeather.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UmbrellaWeather.xcodeproj/project.xcworkspace/xcuserdata/ZeroJian.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather.xcodeproj/project.xcworkspace/xcuserdata/ZeroJian.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /UmbrellaWeather.xcodeproj/xcuserdata/ZeroJian.xcuserdatad/xcschemes/Background Fetch.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 74 | 76 | 82 | 83 | 84 | 85 | 87 | 88 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /UmbrellaWeather.xcodeproj/xcuserdata/ZeroJian.xcuserdatad/xcschemes/UmbrellaWeather.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /UmbrellaWeather.xcodeproj/xcuserdata/ZeroJian.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Background Fetch.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | UmbrellaWeather.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 321599261C3E35CC00F68FA4 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /UmbrellaWeather.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /UmbrellaWeather.xcworkspace/xcuserdata/ZeroJian.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather.xcworkspace/xcuserdata/ZeroJian.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /UmbrellaWeather.xcworkspace/xcuserdata/ZeroJian.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /UmbrellaWeather/Animated/DimmingPresentationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DimmingPresentationController.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 15/12/30. 6 | // Copyright © 2015年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DimmingPresentationController: UIPresentationController{ 12 | override func shouldRemovePresentersView() -> Bool { 13 | return false 14 | } 15 | 16 | lazy var dimmingView = GradientView(frame: CGRect.zero) 17 | override func presentationTransitionWillBegin() { 18 | dimmingView.frame = containerView!.bounds 19 | containerView!.insertSubview(dimmingView, atIndex: 0) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /UmbrellaWeather/Animated/GradientView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GradientView.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 15/12/30. 6 | // Copyright © 2015年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GradientView: UIView{ 12 | 13 | override init(frame: CGRect) { 14 | super.init(frame: frame) 15 | 16 | backgroundColor = UIColor.clearColor() 17 | } 18 | 19 | required init?(coder aDecoder: NSCoder) { 20 | super.init(coder: aDecoder) 21 | backgroundColor = UIColor.clearColor() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /UmbrellaWeather/Animated/InteractiveAnimation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InteractiveAnimation.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/24. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias animationFinshion = (Bool) -> Void 12 | 13 | 14 | func springAnimation1(currtntView: UIView){ 15 | currtntView.transform = CGAffineTransformMakeScale(0.8, 0.8) 16 | UIView.animateWithDuration(0.3, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: [], animations: { () -> Void in 17 | currtntView.transform = CGAffineTransformMakeScale(1.0, 1.0) 18 | }, completion: nil) 19 | } 20 | 21 | func animationWithColor(superView: UIView,color: UIColor){ 22 | UIView.transitionWithView(superView, duration: 1.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: { () -> Void in 23 | superView.backgroundColor = color 24 | }, completion: nil) 25 | } 26 | 27 | func loadingAnimation(imageView: UIImageView){ 28 | if imageView.hidden{ 29 | imageView.hidden = false 30 | } 31 | rotationAnimated(imageView) 32 | } 33 | 34 | private func rotationAnimated(imageView: UIImageView){ 35 | let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z") 36 | rotationAnimation.toValue = NSNumber(double: M_PI * 2.0) 37 | rotationAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) 38 | rotationAnimation.duration = 0.3 39 | rotationAnimation.repeatCount = MAXFLOAT 40 | rotationAnimation.cumulative = false 41 | rotationAnimation.removedOnCompletion = false 42 | rotationAnimation.fillMode = kCAFillModeForwards 43 | imageView.layer.addAnimation(rotationAnimation, forKey: "Rotation") 44 | } 45 | 46 | func launchAnimation(currentView: UIView,finishion: animationFinshion){ 47 | var animationDone = false 48 | let launchView = UIImageView(frame: currentView.bounds) 49 | launchView.imageWithResolution() 50 | currentView.transform = CGAffineTransformMakeScale(0.8, 0.8) 51 | launchView.transform = CGAffineTransformMakeScale(1.25, 1.25) 52 | currentView.addSubview(launchView) 53 | //启动图片扩大消失动画 54 | UIView.animateWithDuration(0.3, delay: 0.9, options: [], animations: { 55 | launchView.transform = CGAffineTransformMakeScale(2.0, 2.0) 56 | launchView.alpha = 0.0 57 | }) { (_) in 58 | launchView.removeFromSuperview() 59 | } 60 | //主视图扩大弹跳动画 61 | UIView.animateWithDuration(0.3, delay: 1.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 1.0, options: [], animations: { () -> Void in 62 | currentView.transform = CGAffineTransformMakeScale(1.0, 1.0) 63 | }){ (_) in 64 | animationDone = true 65 | finishion(animationDone) 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /UmbrellaWeather/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/7. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | var dataModel = DataModel() 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | 19 | let controller = self.window?.rootViewController as! HomeViewController 20 | controller.dataModel = dataModel 21 | 22 | UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(NSTimeInterval(3600 * 12)) 23 | 24 | return true 25 | } 26 | 27 | func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { 28 | let serviceResult = ServiceResult() 29 | serviceResult.fetchDailyResults(dataModel.currentCity) { [weak self] dailyResults in 30 | self?.dataModel.weatherResult.dailyResults = dailyResults 31 | self?.dataModel.saveData() 32 | completionHandler(.NewData) 33 | } 34 | } 35 | 36 | func applicationWillResignActive(application: UIApplication) { 37 | } 38 | 39 | func applicationDidEnterBackground(application: UIApplication) { 40 | saveData() 41 | } 42 | 43 | func applicationWillEnterForeground(application: UIApplication) { 44 | let serviceResult = ServiceResult() 45 | serviceResult.fetchDailyResults(dataModel.currentCity) { [weak self] dailyResults in 46 | self?.dataModel.weatherResult.dailyResults = dailyResults 47 | } 48 | } 49 | 50 | func applicationDidBecomeActive(application: UIApplication) { 51 | 52 | } 53 | 54 | func applicationWillTerminate(application: UIApplication) { 55 | saveData() 56 | } 57 | 58 | func saveData(){ 59 | dataModel.saveData() 60 | } 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /UmbrellaWeather/CityListViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CityListViewController.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/23. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol CityListViewControllerDelegate: class{ 12 | func cityListViewControolerDidSelectCity(controller: CityListViewController, didSelectCity city: City) 13 | func cityListViewControllerCancel(controller: CityListViewController) 14 | func cityListViewControllerDeleteCity(controller: CityListViewController, currentCities cities: [City]) 15 | } 16 | 17 | 18 | class CityListViewController: UIViewController { 19 | 20 | @IBOutlet weak var tableView: UITableView! 21 | @IBOutlet weak var searchBar: UISearchBar! 22 | @IBOutlet weak var headerView: UIView! 23 | @IBOutlet weak var headerYConstraion: NSLayoutConstraint! 24 | weak var delegate: CityListViewControllerDelegate? 25 | 26 | var cities = [City]() 27 | var filteredCities = [City]() 28 | var parserCities = [City]() 29 | var parserXML:ParserXML! 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | tableView.contentInset = UIEdgeInsets(top: 64, left: 0, bottom: 0, right: 0) 34 | headerYConstraion.constant -= view.bounds.height - 60 35 | 36 | let cellNib = UINib(nibName: "CityListCell", bundle: nil) 37 | tableView.registerNib(cellNib, forCellReuseIdentifier: "CityListCell") 38 | } 39 | 40 | override func viewDidAppear(animated: Bool) { 41 | super.viewDidAppear(animated) 42 | headerView.hidden = false 43 | headerYConstraion.constant = 0 44 | 45 | UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in 46 | self.view.layoutIfNeeded() 47 | }, completion: nil) 48 | 49 | } 50 | 51 | func filterControllerForSearchText(searchText: String, scope: String = "ALL"){ 52 | filteredCities = parserCities.filter({ (city) -> Bool in 53 | return city.cityCN.lowercaseString.containsString(searchText.lowercaseString) 54 | }) 55 | tableView.reloadData() 56 | } 57 | 58 | override func didReceiveMemoryWarning() { 59 | super.didReceiveMemoryWarning() 60 | // Dispose of any resources that can be recreated. 61 | } 62 | 63 | deinit{ 64 | parserXML = nil 65 | filteredCities = [] 66 | searchBar.delegate = nil 67 | } 68 | } 69 | 70 | extension CityListViewController: UISearchBarDelegate{ 71 | 72 | func searchBarSearchButtonClicked(searchBar: UISearchBar) { 73 | searchBar.resignFirstResponder() 74 | filterControllerForSearchText(searchBar.text!) 75 | } 76 | 77 | func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { 78 | if parserCities.isEmpty{ 79 | parserXML = ParserXML() 80 | parserCities = parserXML.cities 81 | } 82 | 83 | filterControllerForSearchText(searchText) 84 | } 85 | } 86 | 87 | extension CityListViewController : UITableViewDelegate{ 88 | 89 | func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 90 | if let delegate = delegate{ 91 | let city: City 92 | 93 | if !filteredCities.isEmpty{ 94 | city = filteredCities[indexPath.row] 95 | }else{ 96 | city = cities[indexPath.row] 97 | } 98 | delegate.cityListViewControolerDidSelectCity(self, didSelectCity: city) 99 | } 100 | searchBar.resignFirstResponder() 101 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 102 | 103 | } 104 | 105 | func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { 106 | if searchBar.text != ""{ 107 | return false 108 | }else{ 109 | return true 110 | } 111 | } 112 | 113 | func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 114 | cities.removeAtIndex(indexPath.row) 115 | tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 116 | delegate?.cityListViewControllerDeleteCity(self, currentCities: cities) 117 | } 118 | 119 | func scrollViewDidScroll(scrollView: UIScrollView) { 120 | let offSetY = scrollView.contentOffset.y 121 | searchBar.resignFirstResponder() 122 | 123 | if offSetY < -64{ 124 | headerYConstraion.constant = -(abs(offSetY) - 64) 125 | }else{ 126 | headerYConstraion.constant = 0 127 | } 128 | 129 | } 130 | 131 | func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { 132 | 133 | let offSetY = scrollView.contentOffset.y 134 | 135 | if decelerate && offSetY < -110{ 136 | headerView.hidden = true 137 | delegate?.cityListViewControllerCancel(self) 138 | } 139 | } 140 | 141 | } 142 | 143 | extension CityListViewController: UITableViewDataSource{ 144 | 145 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 146 | 147 | let city: City 148 | if searchBar.text != ""{ 149 | let cell = tableView.dequeueReusableCellWithIdentifier("CityCell", forIndexPath: indexPath) 150 | cell.textLabel?.textColor = UIColor.whiteColor() 151 | city = filteredCities[indexPath.row] 152 | cell.textLabel?.text = city.cityCN 153 | return cell 154 | }else{ 155 | let cell = tableView.dequeueReusableCellWithIdentifier("CityListCell", forIndexPath: indexPath) as! CityListCell 156 | city = cities[indexPath.row] 157 | cell.addCityName(city) 158 | return cell 159 | } 160 | } 161 | 162 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 163 | if !filteredCities.isEmpty || searchBar.text != ""{ 164 | return filteredCities.count 165 | } 166 | return cities.count 167 | } 168 | 169 | } 170 | 171 | -------------------------------------------------------------------------------- /UmbrellaWeather/DataModel/City.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Citys.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 15/12/25. 6 | // Copyright © 2015年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class City: NSObject,NSCoding{ 12 | var cityCN = "" 13 | 14 | override init(){ 15 | super.init() 16 | } 17 | 18 | 19 | required init?(coder aDecoder: NSCoder) { 20 | cityCN = aDecoder.decodeObjectForKey("CityCN") as! String 21 | super.init() 22 | } 23 | 24 | func encodeWithCoder(aCoder: NSCoder) { 25 | aCoder.encodeObject(cityCN, forKey: "CityCN") 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /UmbrellaWeather/DataModel/DataModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataModel.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/3. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DataModel{ 12 | var currentCity = "" 13 | var dueString = "__ : __" 14 | var shouldRemind = false 15 | var cities = [City]() 16 | // var dailyResults = [DailyResult]() 17 | var weatherResult = WeatherResult() 18 | 19 | init(){ 20 | handleFirstTime() 21 | loadData() 22 | } 23 | 24 | func scheduleNotification(){ 25 | 26 | removeLocalNotification() 27 | 28 | if shouldRemind && currentCity != ""{ 29 | 30 | let formatter = NSDateFormatter() 31 | formatter.dateFormat = "yyyy-MM-ddHH:mm" 32 | 33 | for dailyResult in weatherResult.dailyResults{ 34 | 35 | let dateString = dailyResult.dailyDate 36 | let pop = dailyResult.dailyPop 37 | 38 | let stringFormTime = dateString + dueString 39 | 40 | guard let notificationTime = formatter.dateFromString(stringFormTime) else{ return } 41 | 42 | if pop >= 10 && notificationTime.compare(NSDate()) != .OrderedAscending{ 43 | 44 | let localNotification = UILocalNotification() 45 | localNotification.timeZone = NSTimeZone.defaultTimeZone() 46 | localNotification.soundName = "WaterSound.wav" 47 | let alertBody = "\(dateString) \(dailyResult.dailyState) 今天下雨几率为 \(pop) 记得带伞☂" 48 | localNotification.fireDate = notificationTime 49 | localNotification.alertBody = alertBody 50 | UIApplication.sharedApplication().scheduleLocalNotification(localNotification) 51 | } 52 | } 53 | guard let dataString = weatherResult.dailyResults.last?.dailyDate else{ 54 | return 55 | } 56 | let localNotification = UILocalNotification() 57 | let dueTime = formatter.dateFromString(dataString + dueString) 58 | localNotification.timeZone = NSTimeZone.defaultTimeZone() 59 | localNotification.soundName = "WaterSound.wav" 60 | localNotification.fireDate = dueTime!.dateByAddingTimeInterval(30) 61 | localNotification.alertBody = "你已经一周没有打开过软件,提醒通知将取消" 62 | UIApplication.sharedApplication().scheduleLocalNotification(localNotification) 63 | } 64 | } 65 | 66 | private func removeLocalNotification(){ 67 | let allNotifications = UIApplication.sharedApplication().scheduledLocalNotifications 68 | if let allNotifications = allNotifications where !allNotifications.isEmpty{ 69 | UIApplication.sharedApplication().cancelAllLocalNotifications() 70 | } 71 | } 72 | 73 | func appendCity(city:City){ 74 | for thisCity in cities{ 75 | if thisCity.cityCN == city.cityCN{ 76 | return 77 | } 78 | } 79 | cities.append(city) 80 | } 81 | 82 | 83 | private func documentsDirectory() -> String{ 84 | let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) 85 | return paths[0] 86 | } 87 | 88 | private func dataFilePath() -> String{ 89 | return (documentsDirectory() as NSString).stringByAppendingPathComponent("DataModel.plist") 90 | } 91 | 92 | func saveData(){ 93 | let data = NSMutableData() 94 | let archiver = NSKeyedArchiver(forWritingWithMutableData: data) 95 | archiver.encodeObject(currentCity, forKey: "CurrentCity") 96 | archiver.encodeObject(dueString, forKey: "DueString") 97 | archiver.encodeBool(shouldRemind, forKey: "ShouldRemind") 98 | archiver.encodeObject(cities, forKey: "Cities") 99 | archiver.encodeObject(weatherResult.dailyResults, forKey: "DailyResults") 100 | archiver.finishEncoding() 101 | data.writeToFile(dataFilePath(), atomically: true) 102 | scheduleNotification() 103 | } 104 | 105 | func loadData(){ 106 | let path = dataFilePath() 107 | if NSFileManager.defaultManager().fileExistsAtPath(path){ 108 | if let data = NSData(contentsOfFile: path){ 109 | let unarchiver = NSKeyedUnarchiver(forReadingWithData: data) 110 | currentCity = unarchiver.decodeObjectForKey("CurrentCity") as! String 111 | dueString = unarchiver.decodeObjectForKey("DueString") as! String 112 | shouldRemind = unarchiver.decodeBoolForKey("ShouldRemind") 113 | cities = unarchiver.decodeObjectForKey("Cities") as! [City] 114 | weatherResult.dailyResults = unarchiver.decodeObjectForKey("DailyResults") as! [DailyResult] 115 | unarchiver.finishDecoding() 116 | } 117 | } 118 | } 119 | 120 | //上线的新版本改变了数据结构 121 | func handleFirstTime(){ 122 | let userDefaults = NSUserDefaults.standardUserDefaults() 123 | userDefaults.registerDefaults(["FirstTime":true]) 124 | userDefaults.registerDefaults(["IsOldData":true]) 125 | 126 | let isOldData = userDefaults.boolForKey("IsOldData") 127 | if isOldData{ 128 | let fileMager = NSFileManager() 129 | do{ 130 | try fileMager.removeItemAtPath(dataFilePath()) 131 | }catch{ 132 | print("FirstTime") 133 | } 134 | userDefaults.setBool(false, forKey: "IsOldData") 135 | userDefaults.synchronize() 136 | } 137 | } 138 | 139 | } -------------------------------------------------------------------------------- /UmbrellaWeather/DataModel/ParserXML.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParserXML.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/1. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParserXML: NSObject,NSXMLParserDelegate{ 12 | 13 | private var elementName = "" 14 | var cities = [City]() 15 | 16 | override init(){ 17 | super.init() 18 | parseXMLResource() 19 | } 20 | 21 | private func parseXMLResource(){ 22 | let parser = NSXMLParser(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Citys", ofType: "xml")!)) 23 | if let parser = parser{ 24 | parser.delegate = self 25 | parser.parse() 26 | } 27 | } 28 | 29 | func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) { 30 | self.elementName = elementName 31 | } 32 | 33 | func parser(parser: NSXMLParser, foundCharacters string: String) { 34 | let str = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) 35 | if elementName == "city"{ 36 | let city = City() 37 | // print("xml 解析完成") 38 | city.cityCN = str 39 | cities.append(city) 40 | } 41 | } 42 | 43 | func rangeOfLocation(placemark: String) -> String { 44 | var cityName: String! 45 | let p = placemark.lowercaseString 46 | for (_ , value) in cities.enumerate(){ 47 | if p.rangeOfString(value.cityCN) != nil{ 48 | cityName = value.cityCN 49 | break 50 | } else { 51 | cityName = placemark 52 | } 53 | } 54 | return cityName 55 | } 56 | } -------------------------------------------------------------------------------- /UmbrellaWeather/HomeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeViewController.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/21. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import AudioToolbox 11 | 12 | class HomeViewController: UIViewController,TimePickerViewControllerDelegate,SupportTableViewControllerDelegate,CityListViewControllerDelegate,HomeViewDelegate{ 13 | 14 | @IBOutlet weak var collectionView: UICollectionView! 15 | @IBOutlet weak var homeView: HomeView! 16 | 17 | var serviceResult = ServiceResult() 18 | var dataModel: DataModel! 19 | var observer: AnyObject! 20 | var buttonClicked = false 21 | var soundID: SystemSoundID = 0 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | loadSoundEffect("WaterSound.wav") 26 | launchAnimation(self.view) { (finishion) in 27 | if finishion{ 28 | self.handleFirstTime() 29 | } 30 | } 31 | homeView.showRemindStatus(withTimeString:dataModel.dueString, remind: dataModel.shouldRemind) 32 | homeView.delegate = self 33 | listenForLocation() 34 | } 35 | 36 | override func viewDidDisappear(animated: Bool) { 37 | homeView.initialUI() 38 | } 39 | 40 | 41 | override func didReceiveMemoryWarning() { 42 | super.didReceiveMemoryWarning() 43 | } 44 | 45 | @IBAction func location() { 46 | 47 | buttonClicked = true 48 | 49 | updateWeatherResult() 50 | } 51 | 52 | func updateWeatherResult(){ 53 | homeView.initialUI() 54 | 55 | if dataModel.currentCity == "" || buttonClicked == true{ 56 | buttonClicked = false 57 | locationCity() 58 | }else{ 59 | perforRequest() 60 | } 61 | } 62 | 63 | func listenForLocation() { 64 | observer = NSNotificationCenter.defaultCenter().addObserverForName("Location_Denied", object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { [weak self](_) in 65 | self?.showAlert("没有打开定位服务请在设置中打开定位或上拉搜索选择城市", "好的", againReuqest: false, shouldRemind: false) 66 | }) 67 | } 68 | 69 | deinit { 70 | NSNotificationCenter.defaultCenter().removeObserver(observer) 71 | } 72 | 73 | func locationCity(){ 74 | LocationService.startLocation() 75 | LocationService.sharedManager.afterUpdatedCityAction = { 76 | [weak self] sucess in 77 | if !sucess{ 78 | self?.homeView.loadingAnimationStatus(.Finish) 79 | let message = "定位失败,请稍后重试或上滑视图打开城市搜索" 80 | self?.showAlert(message, "好的", againReuqest: false, shouldRemind: false) 81 | } 82 | self?.showLocationStatus() 83 | } 84 | showLocationStatus() 85 | } 86 | 87 | 88 | func showLocationStatus(){ 89 | switch LocationService.sharedManager.locationStatus{ 90 | case .Loading: 91 | homeView.loadingAnimationStatus(.Loading) 92 | case .Result(let city): 93 | dataModel.currentCity = city 94 | perforRequest() 95 | case .Normal: 96 | return 97 | } 98 | } 99 | 100 | func perforRequest(){ 101 | serviceResult.performResult(dataModel.currentCity) { success in 102 | print("网络请求") 103 | if !success{ 104 | self.homeView.loadingAnimationStatus(.Finish) 105 | let message = "网络请求出现错误,请稍后重试" 106 | self.showAlert(message,"取消", againReuqest: true,shouldRemind: false) 107 | } 108 | self.showRequestStatus() 109 | } 110 | showRequestStatus() 111 | } 112 | 113 | func showRequestStatus(){ 114 | switch serviceResult.state{ 115 | case .Loading: 116 | homeView.loadingAnimationStatus(.Loading) 117 | case .Results(let result): 118 | dataModel.weatherResult = result 119 | updateUI() 120 | homeView.loadingAnimationStatus(.Finish) 121 | case .NoRequest: 122 | let message = "今天服务器请求已经超过访问次数,请明天再试" 123 | showAlert(message,"好的", againReuqest: false,shouldRemind: false) 124 | homeView.loadingAnimationStatus(.Finish) 125 | case .NonsupportCity: 126 | dataModel.currentCity = "" 127 | let message = "很抱歉,服务器暂不支持此城市,请在城市搜索界面查找其他城市" 128 | showAlert(message, "好的", againReuqest: false, shouldRemind: false) 129 | homeView.loadingAnimationStatus(.Finish) 130 | break 131 | case .NoYet: 132 | return 133 | } 134 | } 135 | 136 | func updateUI(){ 137 | homeView.updateUI(dataModel.weatherResult) 138 | collectionView.reloadData() 139 | } 140 | 141 | //设置第一次启动引导 142 | func handleFirstTime(){ 143 | let userDefaults = NSUserDefaults.standardUserDefaults() 144 | let firstTime = userDefaults.boolForKey("FirstTime") 145 | if firstTime{ 146 | let firstView = FirstView.showView(self.view) 147 | firstView.doneButton.addTarget(self, action: #selector(touchBegin), forControlEvents: .TouchUpInside) 148 | firstView.tag = 1000; 149 | userDefaults.setBool(false, forKey: "FirstTime") 150 | userDefaults.synchronize() 151 | }else{ 152 | updateWeatherResult() 153 | } 154 | } 155 | 156 | func touchBegin(){ 157 | self.view .viewWithTag(1000)!.removeFromSuperview() 158 | updateWeatherResult() 159 | } 160 | 161 | func showAlert(message: String, _ actionTitle: String,againReuqest: Bool,shouldRemind: Bool){ 162 | 163 | let alertTitle = shouldRemind ? "确定取消天气通知吗?" : "发生错误" 164 | let alertStyle = shouldRemind ? UIAlertControllerStyle.ActionSheet : .Alert 165 | let actionDoneTitle = shouldRemind ? "取消通知" : "重试" 166 | 167 | let alert = UIAlertController(title: alertTitle, message: message , preferredStyle: alertStyle) 168 | 169 | if againReuqest || shouldRemind{ 170 | let actionRequest = UIAlertAction(title: actionDoneTitle, style: .Default, handler: { (action) -> Void in 171 | if shouldRemind{ 172 | 173 | self.shoudldNotification(false) 174 | }else{ 175 | self.perforRequest() 176 | } 177 | }) 178 | alert.addAction(actionRequest) 179 | } 180 | 181 | let actionCancel = UIAlertAction(title: actionTitle, style: .Default, handler: {(_) in 182 | self.updateUI() 183 | }) 184 | 185 | alert.addAction(actionCancel) 186 | 187 | presentViewController(alert, animated: true, completion: nil) 188 | } 189 | 190 | func shoudldNotification(should: Bool){ 191 | 192 | dataModel.shouldRemind = should 193 | if should{ 194 | playSoundEffect() 195 | let notificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Sound], categories: nil) 196 | UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings) 197 | }else{ 198 | self.dataModel.dueString = "__ : __" 199 | } 200 | homeView.headViewContext(should, timeString: dataModel.dueString) 201 | } 202 | 203 | // MARK: - Sound Effect 204 | func loadSoundEffect(name: String){ 205 | if let path = NSBundle.mainBundle().pathForResource(name, ofType: nil){ 206 | let fileURL = NSURL.fileURLWithPath(path, isDirectory: false) 207 | let error = AudioServicesCreateSystemSoundID(fileURL, &soundID) 208 | if error != kAudioServicesNoError{ 209 | print("Sound Error: \(error), path: \(path)") 210 | } 211 | } 212 | } 213 | 214 | func unloadSoundEffect(){ 215 | AudioServicesDisposeSystemSoundID(soundID) 216 | soundID = 0 217 | } 218 | 219 | func playSoundEffect(){ 220 | AudioServicesPlaySystemSound(soundID) 221 | } 222 | 223 | func timePickerViewControllerDidSelect(controller: TimePickerViewController, didSelectTime time: String) { 224 | dataModel.dueString = time 225 | shoudldNotification(true) 226 | dismissViewControllerAnimated(true, completion: nil) 227 | } 228 | 229 | func timePickerViewControllerDidCancel(controller: TimePickerViewController) { 230 | dismissViewControllerAnimated(true, completion: nil) 231 | } 232 | 233 | func supportTableViewController(controller: SupportTableViewController) { 234 | homeView.initialScrollViewOffset() 235 | self.performSelector(#selector(HomeViewController.updateUI), withObject: nil, afterDelay: 0.3) 236 | dismissViewControllerAnimated(true, completion: nil) 237 | } 238 | 239 | func cityListViewControolerDidSelectCity(controller: CityListViewController, didSelectCity city: City) { 240 | 241 | //减少网络请求次数,相同城市只有动画效果不重新加载网络请求 242 | if dataModel.currentCity == city.cityCN{ 243 | self.performSelector(#selector(HomeViewController.updateUI), withObject: nil, afterDelay: 0.3) 244 | }else{ 245 | dataModel.currentCity = city.cityCN 246 | updateWeatherResult() 247 | } 248 | dataModel.appendCity(city) 249 | homeView.initialScrollViewOffset() 250 | dismissViewControllerAnimated(true, completion: nil) 251 | } 252 | 253 | func cityListViewControllerDeleteCity(controller: CityListViewController, currentCities cities: [City]){ 254 | dataModel.cities = cities 255 | } 256 | 257 | func cityListViewControllerCancel(controller: CityListViewController) { 258 | homeView.initialScrollViewOffset() 259 | self.performSelector(#selector(HomeViewController.updateUI), withObject: nil, afterDelay: 0.3) 260 | dismissViewControllerAnimated(true, completion: nil) 261 | } 262 | 263 | func HomeViewScrollStatus(view: HomeView, status: ScrollStatus, offsety: CGFloat, showTimePicker: Bool) { 264 | switch status { 265 | case .DidScroll: 266 | homeView.remindStatus(dataModel.shouldRemind) 267 | case .EndDragging: 268 | if showTimePicker { 269 | performSegueWithIdentifier("TimePicker", sender: self) 270 | } 271 | if offsety <= -100 && !showTimePicker{ 272 | showAlert("","不取消", againReuqest: false, shouldRemind: true) 273 | } 274 | if offsety >= 260{ 275 | performSegueWithIdentifier("CityList", sender: self) 276 | } 277 | } 278 | } 279 | 280 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 281 | if segue.identifier == "TimePicker"{ 282 | let controller = segue.destinationViewController as! TimePickerViewController 283 | controller.delegate = self 284 | } 285 | if segue.identifier == "SupportView"{ 286 | let controller = segue.destinationViewController as! SupportTableViewController 287 | controller.delegate = self 288 | } 289 | if segue.identifier == "CityList"{ 290 | let controller = segue.destinationViewController as! CityListViewController 291 | controller.delegate = self 292 | controller.cities = dataModel.cities 293 | } 294 | } 295 | } 296 | 297 | 298 | extension HomeViewController: UICollectionViewDataSource{ 299 | func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 300 | return dataModel.weatherResult.dailyResults.count 301 | } 302 | 303 | func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 304 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier("WeekWeatherCell", forIndexPath: indexPath) as! WeekWeatherCell 305 | 306 | let dailyResult = dataModel.weatherResult.dailyResults[indexPath.item] 307 | cell.configureForDailyResult(dailyResult) 308 | 309 | return cell 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /UmbrellaWeather/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 8 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | NSLocationWhenInUseUsageDescription 31 | 32 | UIAppFonts 33 | 34 | DINNextLTPro-Light.otf 35 | 36 | UIBackgroundModes 37 | 38 | fetch 39 | 40 | UIMainStoryboardFile 41 | Main 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UIRequiresFullScreen 47 | 48 | UIStatusBarHidden 49 | 50 | UIStatusBarStyle 51 | UIStatusBarStyleDefault 52 | UISupportedInterfaceOrientations 53 | 54 | UIInterfaceOrientationPortrait 55 | 56 | UIViewControllerBasedStatusBarAppearance 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /UmbrellaWeather/Interface/CityListCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /UmbrellaWeather/Interface/FirstView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 32 | 38 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /UmbrellaWeather/Interface/WeekWeatherCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | DINNextLTPro-Light 10 | DINNextLTPro-Light 11 | DINNextLTPro-Light 12 | DINNextLTPro-Light 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 54 | 60 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /UmbrellaWeather/Server/DailyResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayWeatherResult.swift 3 | // Umbrella Weather 4 | // 5 | // Created by ZeroJianMBP on 15/12/17. 6 | // Copyright © 2015年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class DailyResult: NSObject,NSCoding{ 12 | var dailyTmpMax = "" 13 | var dailyTmpMin = "" 14 | var dailyState = "" 15 | var dailyDate = "" 16 | var dailyPop = 0 17 | var dailyStateCode = 0 18 | 19 | 20 | override init() { 21 | super.init() 22 | } 23 | 24 | 25 | required init?(coder aDecoder: NSCoder) { 26 | dailyTmpMax = aDecoder.decodeObjectForKey("DailyTmpMax") as! String 27 | dailyTmpMin = aDecoder.decodeObjectForKey("DailyTmpMin") as! String 28 | dailyState = aDecoder.decodeObjectForKey("DailyState") as! String 29 | dailyDate = aDecoder.decodeObjectForKey("DailyDate") as! String 30 | dailyPop = aDecoder.decodeIntegerForKey("DailyPop") 31 | dailyStateCode = aDecoder.decodeIntegerForKey("DailyStateCode") 32 | super.init() 33 | } 34 | 35 | func encodeWithCoder(aCoder: NSCoder) { 36 | aCoder.encodeObject(dailyTmpMax, forKey: "DailyTmpMax") 37 | aCoder.encodeObject(dailyTmpMin, forKey: "DailyTmpMin") 38 | aCoder.encodeObject(dailyState, forKey: "DailyState") 39 | aCoder.encodeObject(dailyDate, forKey: "DailyDate") 40 | aCoder.encodeInteger(dailyPop, forKey: "DailyPop") 41 | aCoder.encodeInteger(dailyStateCode, forKey: "DailyStateCode") 42 | } 43 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Server/LocationService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Location.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/4. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreLocation 11 | 12 | 13 | 14 | class LocationService: NSObject,CLLocationManagerDelegate{ 15 | 16 | 17 | var updatingLocation = false 18 | var parserXML:ParserXML? 19 | let geocoder = CLGeocoder() 20 | 21 | static let sharedManager = LocationService() 22 | 23 | enum LocationStatus{ 24 | case Loading 25 | case Result(String) 26 | case Normal 27 | } 28 | 29 | class func startLocation() { 30 | if CLLocationManager.locationServicesEnabled() { 31 | self.sharedManager.locationManager.startUpdatingLocation() 32 | } 33 | } 34 | 35 | 36 | var afterUpdatedCityAction: (Bool -> Void)? 37 | 38 | private(set) var locationStatus: LocationStatus = .Normal 39 | 40 | 41 | 42 | lazy var locationManager: CLLocationManager = { 43 | let locationManager = CLLocationManager() 44 | locationManager.delegate = self 45 | locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters 46 | locationManager.requestWhenInUseAuthorization() 47 | return locationManager 48 | }() 49 | 50 | func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { 51 | 52 | if status == .Denied { 53 | NSNotificationCenter.defaultCenter().postNotificationName("Location_Denied", object: nil) 54 | } 55 | } 56 | 57 | func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 58 | guard let newLocation = locations.last else{ 59 | return 60 | } 61 | locationManager.stopUpdatingLocation() 62 | 63 | 64 | geocoder.reverseGeocodeLocation(newLocation) { (placemarks, error) -> Void in 65 | var sucess = false 66 | self.locationStatus = .Loading 67 | if error != nil{ 68 | 69 | }else if let p = placemarks where !p.isEmpty{ 70 | 71 | if let locality = p.last?.locality{ 72 | self.parserXML = ParserXML() 73 | let cityName = self.parserXML!.rangeOfLocation(locality) 74 | sucess = true 75 | self.locationStatus = .Result(cityName) 76 | self.parserXML = nil 77 | } 78 | } 79 | self.afterUpdatedCityAction?(sucess) 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Server/ServiceResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceResult.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 15/12/21. 6 | // Copyright © 2015年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftyJSON 11 | 12 | typealias ResultComplete = (Bool) -> Void 13 | 14 | class ServiceResult { 15 | 16 | enum State{ 17 | case Loading 18 | case NoRequest 19 | case NonsupportCity 20 | case NoYet 21 | case Results(WeatherResult) 22 | } 23 | 24 | 25 | private(set) var state: State = .NoYet 26 | private var dataTask: NSURLSessionDataTask? = nil 27 | 28 | func performResult(cityName: String,completion: ResultComplete){ 29 | if !cityName.isEmpty{ 30 | 31 | dataTask?.cancel() 32 | state = .Loading 33 | 34 | let url = citySearchText(cityName) 35 | let session = NSURLSession.sharedSession() 36 | dataTask = session.dataTaskWithURL(url) { (data, response, error) -> Void in 37 | var success = false 38 | if error != nil && error?.code == -999{ 39 | print(error) 40 | return 41 | } 42 | if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 ,let data = data{ 43 | success = true 44 | let dictionary = self.parseJSON(data) 45 | let weatherResult = self.parseDictionary(dictionary) 46 | if weatherResult.ServiceStatus == "no more requests"{ 47 | self.state = .NoRequest 48 | }else if weatherResult.ServiceStatus == "unknown city"{ 49 | self.state = .NonsupportCity 50 | }else{ 51 | self.state = .Results(weatherResult) 52 | } 53 | 54 | } 55 | dispatch_async(dispatch_get_main_queue(), { 56 | completion(success) 57 | }) 58 | } 59 | dataTask?.resume() 60 | } 61 | } 62 | 63 | func fetchDailyResults(cityName: String,completion: ([DailyResult] -> Void)?){ 64 | 65 | if !cityName.isEmpty{ 66 | 67 | let url = citySearchText(cityName) 68 | let session = NSURLSession.sharedSession() 69 | let dateTask = session.dataTaskWithURL(url) { (data, response, error) 70 | in 71 | if error != nil{ 72 | return 73 | } 74 | if let data = data{ 75 | let dictionary = self.parseJSON(data) 76 | let dailyResults = self.parseWithDairyResults(dictionary) 77 | completion?(dailyResults) 78 | } 79 | } 80 | dateTask.resume() 81 | } 82 | } 83 | 84 | 85 | private func citySearchText(searchText: String) -> NSURL{ 86 | 87 | //api 每天免费请求次数3000,如果超过请求次数请自行注册 88 | //和风天气网址: http://www.heweather.com 89 | 90 | let apiKeyTest = "cf386feb168149f4a45eb87d4f4b647f" 91 | 92 | let escapedSearchText = searchText.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! 93 | let urlString = String(format: "https://api.heweather.com/x3/weather?city=%@&key="+apiKeyTest,escapedSearchText) 94 | let url = NSURL(string: urlString) 95 | return url! 96 | } 97 | 98 | private func parseJSON(data: NSData) -> JSON{ 99 | return JSON(data: data) 100 | } 101 | 102 | private func parseDictionary(dictionary: JSON) -> WeatherResult{ 103 | let weatherResult = WeatherResult() 104 | let json = dictionary["HeWeather data service 3.0"][0] 105 | if let ServiceState = json["status"].string{ 106 | weatherResult.ServiceStatus = ServiceState 107 | } 108 | 109 | if let jsonCity = json["basic"]["city"].string{ 110 | weatherResult.city = jsonCity 111 | } 112 | if let state = json["now"]["cond"]["txt"].string{ 113 | weatherResult.state = state 114 | } 115 | if let stateCode = json["now"]["cond"]["code"].string{ 116 | weatherResult.stateCode = Int(stateCode)! 117 | } 118 | 119 | let dailyArrays = json["daily_forecast"] 120 | let dailyDayTmp = dailyArrays[0]["tmp"] 121 | if let pop = dailyArrays[0]["pop"].string{ 122 | weatherResult.dayRain = pop 123 | } 124 | if let dayTemMax = dailyDayTmp["max"].string{ 125 | weatherResult.dayTemMax = dayTemMax + "˚" 126 | } 127 | if let dayTmpMin = dailyDayTmp["min"].string{ 128 | weatherResult.dayTmpMin = dayTmpMin + "˚" 129 | } 130 | 131 | for (_,subJson):(String, JSON) in json["daily_forecast"]{ 132 | let dailyResult = DailyResult() 133 | 134 | if let dates = subJson["date"].string{ 135 | dailyResult.dailyDate = dates 136 | } 137 | if let pop = subJson["pop"].string{ 138 | dailyResult.dailyPop = Int(pop)! 139 | } 140 | if let tmpsMax = subJson["tmp"]["max"].string{ 141 | dailyResult.dailyTmpMax = tmpsMax + "˚" 142 | } 143 | if let tmpsMin = subJson["tmp"]["min"].string{ 144 | dailyResult.dailyTmpMin = tmpsMin + "˚" 145 | } 146 | if let conds = subJson["cond"]["txt_d"].string{ 147 | dailyResult.dailyState = conds 148 | } 149 | if let stateCode = subJson["cond"]["code_d"].string{ 150 | dailyResult.dailyStateCode = Int(stateCode)! 151 | } 152 | weatherResult.dailyResults.append(dailyResult) 153 | } 154 | return weatherResult 155 | } 156 | 157 | private func parseWithDairyResults(dictionary: JSON) -> [DailyResult]{ 158 | var dailyResults = [DailyResult]() 159 | let json = dictionary["HeWeather data service 3.0"][0] 160 | for (_,subJson):(String, JSON) in json["daily_forecast"]{ 161 | let dailyResult = DailyResult() 162 | if let dates = subJson["date"].string{ 163 | dailyResult.dailyDate = dates 164 | } 165 | if let pop = subJson["pop"].string{ 166 | dailyResult.dailyPop = Int(pop)! 167 | } 168 | if let tmpsMax = subJson["tmp"]["max"].string{ 169 | dailyResult.dailyTmpMax = tmpsMax + "˚" 170 | } 171 | if let tmpsMin = subJson["tmp"]["min"].string{ 172 | dailyResult.dailyTmpMin = tmpsMin + "˚" 173 | } 174 | if let conds = subJson["cond"]["txt_d"].string{ 175 | dailyResult.dailyState = conds 176 | } 177 | if let stateCode = subJson["cond"]["code_d"].string{ 178 | dailyResult.dailyStateCode = Int(stateCode)! 179 | } 180 | dailyResults.append(dailyResult) 181 | } 182 | return dailyResults 183 | } 184 | 185 | } 186 | 187 | -------------------------------------------------------------------------------- /UmbrellaWeather/Server/UIImageView+WeatherImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+WeatherImage.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/25. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIImageView{ 12 | func imageWithCode(code: Int){ 13 | if code == 100{ 14 | self.image = UIImage(named: "Sun") 15 | }else if code >= 101 && code <= 213{ 16 | self.image = UIImage(named: "Cloudy") 17 | }else if code >= 300 && code <= 313{ 18 | self.image = UIImage(named: "Rain") 19 | }else if code >= 400 && code <= 407{ 20 | self.image = UIImage(named: "Snow") 21 | }else if code >= 500 && code <= 504{ 22 | self.image = UIImage(named: "Fog") 23 | }else{ 24 | self.image = UIImage(named: "Cloudy") 25 | } 26 | } 27 | 28 | func imageWithResolution(){ 29 | let screenheight = UIScreen.mainScreen().bounds.size.height 30 | let scale = UIScreen.mainScreen().scale 31 | let heightRes = screenheight * scale 32 | switch heightRes{ 33 | case 960.0: 34 | self.image = UIImage(named: "Launch4") 35 | case 1136.0: 36 | self.image = UIImage(named: "Launch5") 37 | default: 38 | self.image = UIImage(named: "Launch") 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Server/WeatherResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result.swift 3 | // Umbrella Weather 4 | // 5 | // Created by ZeroJianMBP on 15/12/16. 6 | // Copyright © 2015年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class WeatherResult { 12 | var city = "" 13 | var state = "" 14 | var dayRain = "" 15 | var dayTemMax = "" 16 | var dayTmpMin = "" 17 | var stateCode = 0 18 | var dailyResults = [DailyResult]() 19 | var ServiceStatus = "" 20 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-58.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-87.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-80.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-120.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-121.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-180.png", 37 | "scale" : "3x" 38 | } 39 | ], 40 | "info" : { 41 | "version" : 1, 42 | "author" : "xcode" 43 | } 44 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-120.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-121.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-180.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-58.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-80.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/AppIcon.appiconset/Icon-87.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Arrows.imageset/Arrows.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Arrows.imageset/Arrows.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Arrows.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Arrows.pdf", 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "736h", 7 | "filename" : "IPhone 6PLus.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" : "IPhone6.png", 17 | "minimum-system-version" : "8.0", 18 | "orientation" : "portrait", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "orientation" : "portrait", 23 | "idiom" : "iphone", 24 | "filename" : "IPhone4.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" : "IPhone5.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 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone 6PLus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone 6PLus.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone4.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone5.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Brand Assets.launchimage/IPhone6.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Detail.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Detail.pdf", 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Detail.imageset/Detail.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Detail.imageset/Detail.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/DetailColor.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "DetailColor.pdf", 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/DetailColor.imageset/DetailColor.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/DetailColor.imageset/DetailColor.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Launch.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "IPhone6-1.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "IPhone 6PLus-1.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Launch.imageset/IPhone 6PLus-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Launch.imageset/IPhone 6PLus-1.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Launch.imageset/IPhone6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Launch.imageset/IPhone6-1.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Launch4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "IPhone4-1.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Launch4.imageset/IPhone4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Launch4.imageset/IPhone4-1.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Launch5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "IPhone5-1.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Launch5.imageset/IPhone5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Launch5.imageset/IPhone5-1.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Line.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Line@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Line@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Line.imageset/Line@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Line.imageset/Line@2x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Line.imageset/Line@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Line.imageset/Line@3x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Loading.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Loading@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Loading@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Loading.imageset/Loading@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Loading.imageset/Loading@2x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Loading.imageset/Loading@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Loading.imageset/Loading@3x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Location.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Location@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Location@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Location.imageset/Location@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Location.imageset/Location@2x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Location.imageset/Location@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Location.imageset/Location@3x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Logo.pdf", 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Logo.imageset/Logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Logo.imageset/Logo.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Shape.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Shape@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Shape@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Shape.imageset/Shape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Shape.imageset/Shape@2x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/Shape.imageset/Shape@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/Shape.imageset/Shape@3x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Cloudy.imageset/Cloudy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Cloudy.imageset/Cloudy.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Cloudy.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Cloudy.pdf", 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Fog.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Fog@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "Fog@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Fog.imageset/Fog@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Fog.imageset/Fog@2x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Fog.imageset/Fog@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Fog.imageset/Fog@3x.png -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Rain.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Rain.pdf", 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Rain.imageset/Rain.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Rain.imageset/Rain.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Snow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Snow.pdf", 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Snow.imageset/Snow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Snow.imageset/Snow.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Sun.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Sun9.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Sun.imageset/Sun9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/Assets.xcassets/WeatherImage/Sun.imageset/Sun9.pdf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/DINNextLTPro-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/DINNextLTPro-Light.otf -------------------------------------------------------------------------------- /UmbrellaWeather/Sources/WaterSound.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroJian/UmbrellaWeather/8ae8b0f34246017c781986b3b1f1443a0312ba38/UmbrellaWeather/Sources/WaterSound.wav -------------------------------------------------------------------------------- /UmbrellaWeather/SupportTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SupportTableViewController.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/23. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import StoreKit 11 | 12 | protocol SupportTableViewControllerDelegate: class{ 13 | func supportTableViewController(controller: SupportTableViewController) 14 | } 15 | 16 | 17 | class SupportTableViewController: UITableViewController,SKPaymentTransactionObserver,SKProductsRequestDelegate { 18 | 19 | @IBOutlet weak var loadingImageView: UIImageView! 20 | @IBOutlet weak var row1ImageView: UIImageView! 21 | @IBOutlet weak var row2ImageView: UIImageView! 22 | @IBOutlet weak var row3ImageView: UIImageView! 23 | @IBOutlet weak var row1WidthCon: NSLayoutConstraint! 24 | @IBOutlet weak var row2WidthCon: NSLayoutConstraint! 25 | @IBOutlet weak var row3WidthCon: NSLayoutConstraint! 26 | 27 | weak var delegate:SupportTableViewControllerDelegate? 28 | var request: SKProductsRequest! 29 | var requestPay = false 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | SKPaymentQueue.defaultQueue().addTransactionObserver(self) 34 | } 35 | 36 | deinit{ 37 | if requestPay{ 38 | request.delegate = nil 39 | } 40 | SKPaymentQueue.defaultQueue().removeTransactionObserver(self) 41 | } 42 | 43 | 44 | 45 | func requestProducts(pid: String){ 46 | let set: Set = [pid] 47 | request = SKProductsRequest(productIdentifiers: set) 48 | request.delegate = self 49 | request.start() 50 | requestPay = true 51 | } 52 | 53 | 54 | func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) { 55 | buyProduct(response.products[0]) 56 | } 57 | 58 | func buyProduct(product: SKProduct){ 59 | let payment = SKPayment(product: product) 60 | SKPaymentQueue.defaultQueue().addPayment(payment) 61 | print("请求线程购买") 62 | } 63 | 64 | func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { 65 | 66 | for transaction in transactions { 67 | print("队列状态变化 \(transaction.payment.productIdentifier)==\(transaction.transactionState.rawValue))") 68 | switch transaction.transactionState { 69 | case .Purchasing: 70 | print("商品添加进列表 \(transaction.payment.productIdentifier)") 71 | case .Purchased: 72 | switch transaction.payment.productIdentifier{ 73 | case "UmbrellaWeather_1": 74 | row1WidthCon.constant = 0 75 | hiddenLoadingImageView(row1ImageView) 76 | case "UmbrellaWeather_6": 77 | row2WidthCon.constant = 0 78 | hiddenLoadingImageView(row2ImageView) 79 | case "UmbrellaWeather_18": 80 | row3WidthCon.constant = 0 81 | hiddenLoadingImageView(row3ImageView) 82 | default: 83 | break 84 | } 85 | self.finishTransaction(transaction) 86 | case .Failed: 87 | if transaction.error?.code == 0{ 88 | showAlert("感谢你的支持,无法连接到 iTunes Store,请稍后重试") 89 | } 90 | switch transaction.payment.productIdentifier{ 91 | case "UmbrellaWeather_1": 92 | row1WidthCon.constant = 0 93 | hiddenLoadingImageView(row1ImageView) 94 | case "UmbrellaWeather_6": 95 | row2WidthCon.constant = 0 96 | hiddenLoadingImageView(row2ImageView) 97 | case "UmbrellaWeather_18": 98 | row3WidthCon.constant = 0 99 | hiddenLoadingImageView(row3ImageView) 100 | default: 101 | break 102 | } 103 | print("交易失败error==\(transaction.error)") 104 | self.finishTransaction(transaction) 105 | case .Restored: 106 | print("已经购买过商品") 107 | self.finishTransaction(transaction) 108 | case .Deferred: 109 | print("Allow the user to continue using your app.") 110 | break 111 | } 112 | } 113 | } 114 | 115 | 116 | func finishTransaction(transaction:SKPaymentTransaction) { 117 | // 将交易从交易队列中删除 118 | SKPaymentQueue.defaultQueue().finishTransaction(transaction) 119 | } 120 | 121 | override func didReceiveMemoryWarning() { 122 | super.didReceiveMemoryWarning() 123 | // Dispose of any resources that can be recreated. 124 | } 125 | 126 | 127 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 128 | 129 | switch (indexPath.section,indexPath.row){ 130 | 131 | case (1,0): 132 | UIApplication.sharedApplication().openURL(NSURL(string: "itms-apps://itunes.apple.com/app/id" + "1079751819")!) 133 | case (2,0): 134 | requestProducts("UmbrellaWeather_1") 135 | row1WidthCon.constant = row1ImageView.bounds.height 136 | loadingAnimation(row1ImageView) 137 | case (2,1): 138 | requestProducts("UmbrellaWeather_6") 139 | row2WidthCon.constant = row2ImageView.bounds.height 140 | loadingAnimation(row2ImageView) 141 | case (2,2): 142 | requestProducts("UmbrellaWeather_18") 143 | row3WidthCon.constant = row3ImageView.bounds.height 144 | loadingAnimation(row3ImageView) 145 | default: 146 | return 147 | } 148 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 149 | } 150 | 151 | func hiddenLoadingImageView(imageView: UIImageView){ 152 | imageView.layer.removeAllAnimations() 153 | imageView.hidden = true 154 | } 155 | 156 | func showAlert(message: String){ 157 | let alert = UIAlertController(title: "加载错误", message: message, preferredStyle: UIAlertControllerStyle.Alert) 158 | let action = UIAlertAction(title: "好的", style: UIAlertActionStyle.Cancel, handler: nil) 159 | alert.addAction(action) 160 | presentViewController(alert, animated: true, completion: nil) 161 | 162 | } 163 | 164 | 165 | 166 | override func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { 167 | let offSety = scrollView.contentOffset.y 168 | 169 | if offSety < -50 && decelerate{ 170 | delegate?.supportTableViewController(self) 171 | } 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /UmbrellaWeather/TimePickerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimePickerViewController.swift 3 | // UmberellaWeather 4 | // 5 | // Created by ZeroJianMBP on 15/12/27. 6 | // Copyright © 2015年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol TimePickerViewControllerDelegate: class{ 12 | func timePickerViewControllerDidSelect(controller: TimePickerViewController, didSelectTime time: String) 13 | func timePickerViewControllerDidCancel(controller: TimePickerViewController) 14 | } 15 | 16 | class TimePickerViewController: UIViewController { 17 | @IBOutlet weak var datePicker: UIDatePicker! 18 | 19 | weak var delegate: TimePickerViewControllerDelegate? 20 | 21 | 22 | @IBAction func cancel(sender: AnyObject) { 23 | delegate?.timePickerViewControllerDidCancel(self) 24 | } 25 | 26 | @IBAction func done(sender: AnyObject) { 27 | let formatter = NSDateFormatter() 28 | formatter.dateFormat = "HH:mm" 29 | let dateString = formatter.stringFromDate(datePicker.date) 30 | 31 | delegate?.timePickerViewControllerDidSelect(self, didSelectTime: dateString) 32 | } 33 | 34 | override func viewDidLoad() { 35 | super.viewDidLoad() 36 | view.backgroundColor = UIColor.clearColor() 37 | } 38 | 39 | required init?(coder aDecoder: NSCoder) { 40 | super.init(coder: aDecoder) 41 | modalPresentationStyle = .Custom 42 | transitioningDelegate = self 43 | } 44 | } 45 | 46 | extension TimePickerViewController: UIViewControllerTransitioningDelegate{ 47 | func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController? { 48 | return DimmingPresentationController(presentedViewController: presented, presentingViewController: presenting) 49 | } 50 | } -------------------------------------------------------------------------------- /UmbrellaWeather/UIcolor+otherColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIcolor+otherColor.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/5/4. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor { 12 | 13 | class func rainColor() -> UIColor { 14 | return UIColor(red: 98/255, green: 203/255, blue: 238/255, alpha: 1) 15 | } 16 | 17 | class func shallowBlack() -> UIColor { 18 | return UIColor(red: 32/255, green: 32/255, blue: 41/255, alpha: 1) 19 | } 20 | 21 | class func GreenBlue() -> UIColor { 22 | return UIColor(red: 21/255, green: 167/255, blue: 230/255, alpha: 1) 23 | } 24 | } -------------------------------------------------------------------------------- /UmbrellaWeather/View/CityListCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CityListCell.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/29. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CityListCell: UITableViewCell{ 12 | 13 | @IBOutlet weak var cityLabel: UILabel! 14 | 15 | func addCityName(city: City){ 16 | cityLabel.text = city.cityCN 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/FirstView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstView.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/28. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FirstView: UIView { 12 | 13 | var doneButton: UIButton! 14 | 15 | override init(frame: CGRect) { 16 | super.init(frame: frame) 17 | loadViewFormNib() 18 | } 19 | 20 | required init?(coder aDecoder: NSCoder) { 21 | super.init(coder: aDecoder) 22 | loadViewFormNib() 23 | fatalError("init(coder:) has not been implemented") 24 | } 25 | 26 | func loadViewFormNib(){ 27 | let bundle = NSBundle(forClass: self.dynamicType) 28 | let nib = UINib(nibName: "FirstView", bundle: bundle) 29 | let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView 30 | view.frame = bounds 31 | self.addSubview(view) 32 | } 33 | 34 | class func showView(superview: UIView) -> FirstView { 35 | let firstView = FirstView() 36 | firstView.frame = superview.bounds 37 | superview.addSubview(firstView) 38 | 39 | firstView.doneButton = UIButton() 40 | firstView.doneButton.bounds.size = CGSize(width: 100, height: 50) 41 | firstView.doneButton.center = firstView.center 42 | firstView.doneButton.setTitle("开始吧!", forState: .Normal) 43 | firstView.doneButton.backgroundColor = UIColor.rainColor() 44 | firstView.addSubview(firstView.doneButton) 45 | return firstView 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/HeadView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeadView.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/5/4. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class HeadView: UIView { 12 | 13 | @IBOutlet weak var detailButton: UIButton! 14 | @IBOutlet weak var cityButton: UIButton! 15 | @IBOutlet weak var dateView: UIView! 16 | @IBOutlet weak var dateLabel: UILabel! 17 | 18 | 19 | var timeString: String! 20 | 21 | var endDragging: Bool? { 22 | willSet{ 23 | dateView.backgroundColor = UIColor.shallowBlack() 24 | if dateString != nil { 25 | dateLabel.text = dateString 26 | } 27 | } 28 | } 29 | 30 | var dateString: String! 31 | 32 | var shoudRemind: Bool! { 33 | willSet { 34 | springAnimation1(dateView) 35 | dateView.backgroundColor = UIColor.rainColor() 36 | dateLabel.text = timeString 37 | remindStatus = newValue 38 | if newValue == true { 39 | detailButton.setBackgroundImage(UIImage(named: "DetailColor"), forState: .Normal) 40 | } else if newValue == false { 41 | detailButton.setBackgroundImage(UIImage(named: "Detail"), forState: .Normal) 42 | } 43 | } 44 | } 45 | 46 | var remindStatus: Bool! 47 | 48 | var offsetY: CGFloat! { 49 | willSet { 50 | if newValue <= -60 { 51 | dateLabel.text = timeString 52 | dateView.backgroundColor = self.tintColor 53 | if remindStatus == true && newValue <= -100 { 54 | dateLabel.text = timeString 55 | dateView.backgroundColor = UIColor.shallowBlack() 56 | } 57 | } else { 58 | if dateString != "" { 59 | dateLabel.text = dateString 60 | } 61 | dateView.backgroundColor = UIColor.shallowBlack() 62 | } 63 | } 64 | } 65 | 66 | 67 | override init(frame: CGRect) { 68 | super.init(frame: frame) 69 | } 70 | 71 | required init(coder aDecoder: NSCoder) { 72 | super.init(coder: aDecoder)! 73 | } 74 | 75 | func initialTextString() { 76 | cityButton.titleLabel?.text = " " 77 | cityButton.setTitle(" ", forState: .Normal) 78 | dateLabel.text = "" 79 | } 80 | 81 | func updateUI(cityName: String!) { 82 | cityButton.setTitle(cityName, forState: .Normal) 83 | 84 | if dateString != nil { 85 | dateLabel.text = dateString 86 | } else { 87 | let currentdate = NSDate() 88 | let dateFormatter = NSDateFormatter() 89 | dateFormatter.dateFormat = "EEEE" 90 | let convertedDate = dateFormatter.stringFromDate(currentdate) 91 | dateLabel.text = convertedDate 92 | dateString = convertedDate 93 | } 94 | } 95 | 96 | @IBAction func headButton() { 97 | print("head button tap") 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/HomeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeView.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/5/4. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum ScrollStatus { 12 | case DidScroll; 13 | case EndDragging; 14 | } 15 | 16 | protocol HomeViewDelegate: class { 17 | func HomeViewScrollStatus(view: HomeView, status: ScrollStatus,offsety: CGFloat,showTimePicker: Bool) 18 | } 19 | 20 | class HomeView: UIView { 21 | 22 | 23 | @IBOutlet weak var scorllView: MainScrollView! { 24 | didSet { 25 | scorllView.delegate = self 26 | } 27 | } 28 | 29 | @IBOutlet weak var headView: HeadView! 30 | 31 | enum LoadingAnimation { 32 | case Loading 33 | case Finish 34 | } 35 | 36 | weak var delegate: HomeViewDelegate? 37 | 38 | var showTimePicker: Bool! 39 | 40 | var shouldRemind: Bool! 41 | 42 | var endDragging: Bool! 43 | 44 | func showRemindStatus(withTimeString time: String, remind: Bool) { 45 | headView.timeString = time 46 | headView.remindStatus = remind 47 | if remind { 48 | headView.detailButton.setBackgroundImage(UIImage(named: "DetailColor"), forState: .Normal) 49 | } 50 | } 51 | 52 | func loadingAnimationStatus(stauts:LoadingAnimation) { 53 | switch stauts { 54 | case .Loading: 55 | if !scorllView.weatherView.loading { 56 | scorllView.weatherView.loadingAnimated() 57 | } 58 | case .Finish: 59 | scorllView.weatherView.loadingFinish() 60 | } 61 | } 62 | 63 | func remindStatus(status: Bool) { 64 | scorllView.pullDownView.shoudRemind = status 65 | shouldRemind = status 66 | } 67 | 68 | func initialScrollViewOffset() { 69 | scorllView.setContentOffset(CGPoint(x: 0, y: 0), animated: false) 70 | } 71 | 72 | func headViewContext(should: Bool,timeString: String) { 73 | headView.timeString = timeString 74 | headView.shoudRemind = should 75 | } 76 | 77 | func endScroll(end: Bool) { 78 | scorllView.pullDownView.endDragging = end 79 | headView.endDragging = end 80 | } 81 | 82 | func initialUI() { 83 | scorllView.weatherView.animationBegin() 84 | headView.initialTextString() 85 | } 86 | 87 | func updateUI(weatherResult: WeatherResult) { 88 | if weatherResult.city == "" { 89 | return 90 | } 91 | scorllView.weatherView.updateAndAnimation(weatherResult) 92 | headView.updateUI(weatherResult.city) 93 | } 94 | 95 | 96 | override init(frame: CGRect) { 97 | super.init(frame: frame) 98 | } 99 | 100 | required init(coder aDecoder: NSCoder) { 101 | super.init(coder: aDecoder)! 102 | } 103 | } 104 | 105 | extension HomeView: UIScrollViewDelegate { 106 | func scrollViewDidScroll(scrollView: UIScrollView) { 107 | let offSety = scrollView.contentOffset.y 108 | showTimePicker = false 109 | 110 | if offSety < -85 { 111 | showTimePicker = true 112 | if shouldRemind == true && offSety <= -100 { 113 | showTimePicker = false 114 | } 115 | } 116 | 117 | headView.offsetY = offSety 118 | scorllView.didScroll(offSety) 119 | delegate?.HomeViewScrollStatus(self, status: .DidScroll, offsety: offSety, showTimePicker: false) 120 | } 121 | 122 | func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { 123 | let offSety = scrollView.contentOffset.y 124 | if decelerate == true { 125 | endScroll(decelerate) 126 | delegate?.HomeViewScrollStatus(self, status: .EndDragging, offsety: offSety, showTimePicker: showTimePicker) 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/MainScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainScrollView.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/5/4. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | //protocol MainScrollViewDelegate: class { 12 | // func offsetYOfMainScrollView(view: MainScrollView,offsetY: CGFloat) 13 | // func endScrollOfMainScrollView(view: MainScrollView) -> Bool! 14 | // 15 | //} 16 | 17 | 18 | class MainScrollView: UIScrollView { 19 | 20 | @IBOutlet weak var weatherView: WeatherView! 21 | @IBOutlet weak var pullDownView: PullView! 22 | 23 | 24 | func didScroll(offsetY: CGFloat) { 25 | pullDownView.offsetY = offsetY 26 | weatherView.offsetY = offsetY 27 | } 28 | 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/PullView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PullViewController.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/24. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PullView: UIView { 12 | 13 | 14 | @IBOutlet weak var remindLabel: UILabel! 15 | @IBOutlet weak var lineImage: UIImageView! 16 | @IBOutlet weak var lineXConstraion: NSLayoutConstraint! 17 | @IBOutlet weak var topHeightConstraion: NSLayoutConstraint! 18 | @IBOutlet weak var buttonHeightConstraion: NSLayoutConstraint! 19 | 20 | 21 | var shoudRemind: Bool! { 22 | willSet { 23 | if newValue == true { 24 | remindString = "释放更换通知时间" 25 | if offsetY <= -100 { 26 | remindLabel.text = "释放取消通知" 27 | remindLabel.textColor = UIColor.GreenBlue() 28 | animationWithColor(self, color: UIColor.shallowBlack()) 29 | } 30 | }else if newValue == false { 31 | remindString = "释放激活下雨通知" 32 | } 33 | } 34 | } 35 | 36 | var endDragging: Bool? { 37 | willSet{ 38 | hiddenView() 39 | } 40 | } 41 | 42 | var remindString: String! 43 | 44 | var offsetY: CGFloat! { 45 | willSet { 46 | if newValue < -30 { 47 | lineAnimation() 48 | topHeightConstraion.constant = abs(newValue) 49 | self.hidden = false 50 | if newValue <= -60 && newValue > -100 { 51 | viewDidScroll("↓下拉设置通知", alpha: 0.04 * (abs(newValue) - 60)) 52 | animationWithColor(self,color:UIColor.GreenBlue()) 53 | if newValue < -85 { 54 | viewDidScroll(remindString, alpha: 1) 55 | } 56 | } 57 | } else { 58 | if !self.hidden { 59 | hiddenView() 60 | } 61 | } 62 | } 63 | } 64 | 65 | func viewDidScroll(labelText: String!,alpha: CGFloat){ 66 | remindLabel.hidden = false 67 | remindLabel.text = labelText 68 | remindLabel.textColor = UIColor.whiteColor() 69 | remindLabel.alpha = alpha 70 | } 71 | 72 | 73 | func lineAnimation(){ 74 | lineImage.hidden = false 75 | lineXConstraion.constant = self.bounds.width 76 | UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in 77 | self.layoutIfNeeded() 78 | }, completion: nil) 79 | } 80 | 81 | 82 | func hiddenView(){ 83 | self.hidden = true 84 | remindLabel.hidden = true 85 | remindLabel.alpha = 0 86 | lineImage.hidden = true 87 | topHeightConstraion.constant = 0 88 | self.backgroundColor = UIColor.shallowBlack() 89 | lineXConstraion.constant -= lineImage.bounds.width 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/WeatherView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeatherView.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/23. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class WeatherView: UIView { 12 | 13 | 14 | @IBOutlet weak var weatherImage: UIImageView! 15 | @IBOutlet weak var tmpMaxLabel: UILabel! 16 | @IBOutlet weak var tmpMinLabel: UILabel! 17 | @IBOutlet weak var rainPercentLabel: UILabel! 18 | @IBOutlet weak var schemaLabel: UILabel! 19 | @IBOutlet weak var progress: UIProgressView! 20 | @IBOutlet weak var maxLabelConstraint: NSLayoutConstraint! 21 | @IBOutlet weak var minLabelConstraint: NSLayoutConstraint! 22 | @IBOutlet weak var percentConstraint: NSLayoutConstraint! 23 | var loadingImageView: UIImageView! 24 | var loading = false 25 | 26 | var offsetY: CGFloat! { 27 | didSet { 28 | if offsetY >= 40 && offsetY <= 140 { 29 | weatherImage.alpha = 1 - (0.02 * (offsetY - 30)) 30 | } else { 31 | weatherImage.alpha = 1 32 | } 33 | } 34 | } 35 | 36 | 37 | func updateAndAnimation(weatherResult: WeatherResult){ 38 | animation() 39 | schemaLabel.text = weatherResult.state 40 | weatherImage.imageWithCode(weatherResult.stateCode) 41 | tmpMaxLabel.text = weatherResult.dayTemMax 42 | tmpMinLabel.text = weatherResult.dayTmpMin 43 | if let FloatRain = Float(weatherResult.dayRain){ 44 | let value = FloatRain / 100 45 | progress.setProgress(value, animated: true) 46 | } 47 | rainPercentLabel.text = weatherResult.dayRain + "%" 48 | } 49 | 50 | func loadingAnimated(){ 51 | loadingImageView = UIImageView(image: UIImage(named: "Loading")!) 52 | loadingImageView.center.x = self.center.x 53 | loadingImageView.center.y = self.center.y - 50 54 | loadingImageView.bounds.size.width = self.bounds.size.width / 5 55 | loadingImageView.bounds.size.height = loadingImageView.bounds.size.width 56 | self.addSubview(loadingImageView) 57 | loadingAnimation(loadingImageView) 58 | loading = true 59 | } 60 | 61 | func loadingFinish(){ 62 | loadingImageView.layer.removeAllAnimations() 63 | loadingImageView.removeFromSuperview() 64 | loading = false 65 | } 66 | 67 | func animationBegin(){ 68 | maxLabelConstraint.constant = 25 69 | minLabelConstraint.constant = 25 70 | percentConstraint.constant = 10 71 | weatherImage.hidden = true 72 | weatherImage.transform = CGAffineTransformMakeScale(0.7, 0.7) 73 | schemaLabel.text = "" 74 | tmpMaxLabel.text = "" 75 | tmpMinLabel.text = "" 76 | rainPercentLabel.text = "" 77 | } 78 | 79 | private func animation(){ 80 | UIView.animateWithDuration(0.66, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: .CurveEaseInOut, animations: { () -> Void in 81 | self.weatherImage.hidden = false 82 | self.weatherImage.transform = CGAffineTransformMakeScale(1.0, 1.0) 83 | }, completion: nil) 84 | self.maxLabelConstraint.constant = 5 85 | UIView.animateWithDuration(0.66, delay: 0.0, options: .CurveEaseInOut, animations: { () -> Void in 86 | self.layoutIfNeeded() 87 | }, completion: nil) 88 | UIView.animateWithDuration(0.66, delay: 0.2, options: .CurveEaseInOut, animations: { () -> Void in 89 | self.minLabelConstraint.constant = 5 90 | self.layoutIfNeeded() 91 | }, completion: nil) 92 | UIView.animateWithDuration(0.66, delay: 0.2, options: .CurveEaseInOut, animations: { () -> Void in 93 | self.percentConstraint.constant = 30 94 | self.layoutIfNeeded() 95 | }, completion: nil) 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/WeekWeatherCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeekWeatherCell.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/21. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class WeekWeatherCell: UICollectionViewCell{ 12 | @IBOutlet weak var dateLabel: UILabel! 13 | @IBOutlet weak var weatherImage: UIImageView! 14 | @IBOutlet weak var tmpMaxLabel: UILabel! 15 | @IBOutlet weak var tmpMinLabel: UILabel! 16 | @IBOutlet weak var rainPercentLabel: UILabel! 17 | @IBOutlet weak var schemaLabel: UILabel! 18 | 19 | override func awakeFromNib() { 20 | super.awakeFromNib() 21 | } 22 | 23 | func configureForDailyResult(dailyResult: DailyResult){ 24 | dateLabel.text = dailyResult.dailyDate 25 | schemaLabel.text = dailyResult.dailyState 26 | tmpMaxLabel.text = dailyResult.dailyTmpMax + " /" 27 | tmpMinLabel.text = dailyResult.dailyTmpMin 28 | rainPercentLabel.text = 29 | "\(dailyResult.dailyPop)" + "%" 30 | weatherImage.imageWithCode(dailyResult.dailyStateCode) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /UmbrellaWeather/View/WeekWeatherCollectionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeekWeatherCollectionView.swift 3 | // UmbrellaWeather 4 | // 5 | // Created by ZeroJianMBP on 16/1/23. 6 | // Copyright © 2016年 ZeroJian. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class WeekWeatherCollectionView: UICollectionView { 12 | 13 | 14 | required init?(coder aDecoder: NSCoder) { 15 | super.init(coder: aDecoder) 16 | let cellNib = UINib(nibName: "WeekWeatherCell", bundle: nil) 17 | self.registerNib(cellNib, forCellWithReuseIdentifier: "WeekWeatherCell") 18 | } 19 | 20 | } 21 | --------------------------------------------------------------------------------