├── AppUI.png ├── FM_ycm.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── FM_ycm ├── Base.lproj │ └── Main.storyboard ├── CONSTANTS.h ├── Channel.h ├── Channel.m ├── ChannelsViewController.h ├── ChannelsViewController.m ├── FMAppDelegate.h ├── FMAppDelegate.m ├── FMViewController.h ├── FMViewController.m ├── FM_ycm-Info.plist ├── FM_ycm-Prefix.pch ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ └── Contents.json │ └── png │ │ ├── 0.imageset │ │ ├── 0.png │ │ └── Contents.json │ │ ├── 1.imageset │ │ ├── 1.png │ │ └── Contents.json │ │ ├── 10.imageset │ │ ├── 10.png │ │ └── Contents.json │ │ ├── 11.imageset │ │ ├── 11.png │ │ └── Contents.json │ │ ├── 12.imageset │ │ ├── 12.png │ │ └── Contents.json │ │ ├── 13.imageset │ │ ├── 13.png │ │ └── Contents.json │ │ ├── 2.imageset │ │ ├── 2.png │ │ └── Contents.json │ │ ├── 3.imageset │ │ ├── 3.png │ │ └── Contents.json │ │ ├── 4.imageset │ │ ├── 4.png │ │ └── Contents.json │ │ ├── 5.imageset │ │ ├── 5.png │ │ └── Contents.json │ │ ├── 6.imageset │ │ ├── 6.png │ │ └── Contents.json │ │ ├── 7.imageset │ │ ├── 7.png │ │ └── Contents.json │ │ ├── 8.imageset │ │ ├── 8.png │ │ └── Contents.json │ │ └── 9.imageset │ │ ├── 9.png │ │ └── Contents.json ├── LoginViewController.h ├── LoginViewController.m ├── Model.xcdatamodeld │ └── Model.xcdatamodel │ │ └── contents ├── Track.h ├── Track.m ├── User.h ├── User.m ├── en.lproj │ └── InfoPlist.strings └── main.m ├── FM_ycmTests ├── FM_ycmTests-Info.plist ├── FM_ycmTests.m └── en.lproj │ └── InfoPlist.strings └── README.md /AppUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/AppUI.png -------------------------------------------------------------------------------- /FM_ycm.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7946C10618A0AA4500E0C692 /* ChannelsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7946C10518A0AA4500E0C692 /* ChannelsViewController.m */; }; 11 | 7946C10A18A0B42600E0C692 /* Channel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7946C10918A0B42600E0C692 /* Channel.m */; }; 12 | 7946C10D18A10F4B00E0C692 /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7946C10C18A10F4B00E0C692 /* LoginViewController.m */; }; 13 | 798107061892184D00299905 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 798107051892184D00299905 /* Foundation.framework */; }; 14 | 798107081892184D00299905 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 798107071892184D00299905 /* CoreGraphics.framework */; }; 15 | 7981070A1892184D00299905 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 798107091892184D00299905 /* UIKit.framework */; }; 16 | 798107101892184D00299905 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7981070E1892184D00299905 /* InfoPlist.strings */; }; 17 | 798107121892184D00299905 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 798107111892184D00299905 /* main.m */; }; 18 | 798107161892184D00299905 /* FMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 798107151892184D00299905 /* FMAppDelegate.m */; }; 19 | 798107191892184D00299905 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 798107171892184D00299905 /* Main.storyboard */; }; 20 | 7981071C1892184D00299905 /* FMViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7981071B1892184D00299905 /* FMViewController.m */; }; 21 | 7981071E1892184D00299905 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7981071D1892184D00299905 /* Images.xcassets */; }; 22 | 798107251892184D00299905 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 798107241892184D00299905 /* XCTest.framework */; }; 23 | 798107261892184D00299905 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 798107051892184D00299905 /* Foundation.framework */; }; 24 | 798107271892184D00299905 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 798107091892184D00299905 /* UIKit.framework */; }; 25 | 7981072F1892184D00299905 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7981072D1892184D00299905 /* InfoPlist.strings */; }; 26 | 798107311892184D00299905 /* FM_ycmTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 798107301892184D00299905 /* FM_ycmTests.m */; }; 27 | 799F3FBA18A79300003871F8 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 799F3FB818A79300003871F8 /* Model.xcdatamodeld */; }; 28 | 799F3FBD18A79411003871F8 /* User.m in Sources */ = {isa = PBXBuildFile; fileRef = 799F3FBC18A79411003871F8 /* User.m */; }; 29 | 79A8E87718977A39007CF082 /* Track.m in Sources */ = {isa = PBXBuildFile; fileRef = 79A8E87618977A39007CF082 /* Track.m */; }; 30 | 79EF948418AB859A004BC175 /* AppUI.png in Resources */ = {isa = PBXBuildFile; fileRef = 79EF948318AB859A004BC175 /* AppUI.png */; }; 31 | 844C0539999E47FCAD5A0B2E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3443A088D70A4274B953302F /* libPods.a */; }; 32 | /* End PBXBuildFile section */ 33 | 34 | /* Begin PBXContainerItemProxy section */ 35 | 798107281892184D00299905 /* PBXContainerItemProxy */ = { 36 | isa = PBXContainerItemProxy; 37 | containerPortal = 798106FA1892184D00299905 /* Project object */; 38 | proxyType = 1; 39 | remoteGlobalIDString = 798107011892184D00299905; 40 | remoteInfo = FM_ycm; 41 | }; 42 | /* End PBXContainerItemProxy section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | 3443A088D70A4274B953302F /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 6C05AB7DDF4543A78C0F75A0 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = ""; }; 47 | 7946C10418A0AA4500E0C692 /* ChannelsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChannelsViewController.h; sourceTree = ""; }; 48 | 7946C10518A0AA4500E0C692 /* ChannelsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChannelsViewController.m; sourceTree = ""; }; 49 | 7946C10718A0B19500E0C692 /* CONSTANTS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CONSTANTS.h; sourceTree = ""; }; 50 | 7946C10818A0B42600E0C692 /* Channel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Channel.h; sourceTree = ""; }; 51 | 7946C10918A0B42600E0C692 /* Channel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Channel.m; sourceTree = ""; }; 52 | 7946C10B18A10F4B00E0C692 /* LoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = ""; }; 53 | 7946C10C18A10F4B00E0C692 /* LoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = ""; }; 54 | 798107021892184D00299905 /* FM_ycm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FM_ycm.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 798107051892184D00299905 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 56 | 798107071892184D00299905 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 57 | 798107091892184D00299905 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 58 | 7981070D1892184D00299905 /* FM_ycm-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FM_ycm-Info.plist"; sourceTree = ""; }; 59 | 7981070F1892184D00299905 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 60 | 798107111892184D00299905 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 61 | 798107131892184D00299905 /* FM_ycm-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FM_ycm-Prefix.pch"; sourceTree = ""; }; 62 | 798107141892184D00299905 /* FMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMAppDelegate.h; sourceTree = ""; }; 63 | 798107151892184D00299905 /* FMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMAppDelegate.m; sourceTree = ""; }; 64 | 798107181892184D00299905 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 65 | 7981071A1892184D00299905 /* FMViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMViewController.h; sourceTree = ""; }; 66 | 7981071B1892184D00299905 /* FMViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMViewController.m; sourceTree = ""; }; 67 | 7981071D1892184D00299905 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 68 | 798107231892184D00299905 /* FM_ycmTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FM_ycmTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 798107241892184D00299905 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 70 | 7981072C1892184D00299905 /* FM_ycmTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FM_ycmTests-Info.plist"; sourceTree = ""; }; 71 | 7981072E1892184D00299905 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 72 | 798107301892184D00299905 /* FM_ycmTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FM_ycmTests.m; sourceTree = ""; }; 73 | 799F3FB918A79300003871F8 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = ""; }; 74 | 799F3FBB18A79411003871F8 /* User.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = User.h; sourceTree = ""; }; 75 | 799F3FBC18A79411003871F8 /* User.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = User.m; sourceTree = ""; }; 76 | 79A8E87518977A39007CF082 /* Track.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Track.h; sourceTree = ""; }; 77 | 79A8E87618977A39007CF082 /* Track.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Track.m; sourceTree = ""; }; 78 | 79EF948318AB859A004BC175 /* AppUI.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AppUI.png; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | 798106FF1892184D00299905 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | 798107081892184D00299905 /* CoreGraphics.framework in Frameworks */, 87 | 7981070A1892184D00299905 /* UIKit.framework in Frameworks */, 88 | 798107061892184D00299905 /* Foundation.framework in Frameworks */, 89 | 844C0539999E47FCAD5A0B2E /* libPods.a in Frameworks */, 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | 798107201892184D00299905 /* Frameworks */ = { 94 | isa = PBXFrameworksBuildPhase; 95 | buildActionMask = 2147483647; 96 | files = ( 97 | 798107251892184D00299905 /* XCTest.framework in Frameworks */, 98 | 798107271892184D00299905 /* UIKit.framework in Frameworks */, 99 | 798107261892184D00299905 /* Foundation.framework in Frameworks */, 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | /* End PBXFrameworksBuildPhase section */ 104 | 105 | /* Begin PBXGroup section */ 106 | 7946C10E18A1130A00E0C692 /* model */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 799F3FB818A79300003871F8 /* Model.xcdatamodeld */, 110 | 799F3FBB18A79411003871F8 /* User.h */, 111 | 799F3FBC18A79411003871F8 /* User.m */, 112 | 7946C10818A0B42600E0C692 /* Channel.h */, 113 | 7946C10918A0B42600E0C692 /* Channel.m */, 114 | 79A8E87518977A39007CF082 /* Track.h */, 115 | 79A8E87618977A39007CF082 /* Track.m */, 116 | ); 117 | name = model; 118 | sourceTree = ""; 119 | }; 120 | 798106F91892184D00299905 = { 121 | isa = PBXGroup; 122 | children = ( 123 | 79EF948318AB859A004BC175 /* AppUI.png */, 124 | 7981070B1892184D00299905 /* FM_ycm */, 125 | 7981072A1892184D00299905 /* FM_ycmTests */, 126 | 798107041892184D00299905 /* Frameworks */, 127 | 798107031892184D00299905 /* Products */, 128 | 6C05AB7DDF4543A78C0F75A0 /* Pods.xcconfig */, 129 | ); 130 | sourceTree = ""; 131 | }; 132 | 798107031892184D00299905 /* Products */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 798107021892184D00299905 /* FM_ycm.app */, 136 | 798107231892184D00299905 /* FM_ycmTests.xctest */, 137 | ); 138 | name = Products; 139 | sourceTree = ""; 140 | }; 141 | 798107041892184D00299905 /* Frameworks */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 798107051892184D00299905 /* Foundation.framework */, 145 | 798107071892184D00299905 /* CoreGraphics.framework */, 146 | 798107091892184D00299905 /* UIKit.framework */, 147 | 798107241892184D00299905 /* XCTest.framework */, 148 | 3443A088D70A4274B953302F /* libPods.a */, 149 | ); 150 | name = Frameworks; 151 | sourceTree = ""; 152 | }; 153 | 7981070B1892184D00299905 /* FM_ycm */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 7946C10E18A1130A00E0C692 /* model */, 157 | 798107141892184D00299905 /* FMAppDelegate.h */, 158 | 798107151892184D00299905 /* FMAppDelegate.m */, 159 | 798107171892184D00299905 /* Main.storyboard */, 160 | 7981071A1892184D00299905 /* FMViewController.h */, 161 | 7981071B1892184D00299905 /* FMViewController.m */, 162 | 7946C10418A0AA4500E0C692 /* ChannelsViewController.h */, 163 | 7946C10518A0AA4500E0C692 /* ChannelsViewController.m */, 164 | 7946C10B18A10F4B00E0C692 /* LoginViewController.h */, 165 | 7946C10C18A10F4B00E0C692 /* LoginViewController.m */, 166 | 7981071D1892184D00299905 /* Images.xcassets */, 167 | 7981070C1892184D00299905 /* Supporting Files */, 168 | ); 169 | path = FM_ycm; 170 | sourceTree = ""; 171 | }; 172 | 7981070C1892184D00299905 /* Supporting Files */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 7981070D1892184D00299905 /* FM_ycm-Info.plist */, 176 | 7981070E1892184D00299905 /* InfoPlist.strings */, 177 | 798107111892184D00299905 /* main.m */, 178 | 798107131892184D00299905 /* FM_ycm-Prefix.pch */, 179 | 7946C10718A0B19500E0C692 /* CONSTANTS.h */, 180 | ); 181 | name = "Supporting Files"; 182 | sourceTree = ""; 183 | }; 184 | 7981072A1892184D00299905 /* FM_ycmTests */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | 798107301892184D00299905 /* FM_ycmTests.m */, 188 | 7981072B1892184D00299905 /* Supporting Files */, 189 | ); 190 | path = FM_ycmTests; 191 | sourceTree = ""; 192 | }; 193 | 7981072B1892184D00299905 /* Supporting Files */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | 7981072C1892184D00299905 /* FM_ycmTests-Info.plist */, 197 | 7981072D1892184D00299905 /* InfoPlist.strings */, 198 | ); 199 | name = "Supporting Files"; 200 | sourceTree = ""; 201 | }; 202 | /* End PBXGroup section */ 203 | 204 | /* Begin PBXNativeTarget section */ 205 | 798107011892184D00299905 /* FM_ycm */ = { 206 | isa = PBXNativeTarget; 207 | buildConfigurationList = 798107341892184D00299905 /* Build configuration list for PBXNativeTarget "FM_ycm" */; 208 | buildPhases = ( 209 | 77DD4015365C4A7093553A7C /* Check Pods Manifest.lock */, 210 | 798106FE1892184D00299905 /* Sources */, 211 | 798106FF1892184D00299905 /* Frameworks */, 212 | 798107001892184D00299905 /* Resources */, 213 | F7B88E0FCD904954881E3E0D /* Copy Pods Resources */, 214 | ); 215 | buildRules = ( 216 | ); 217 | dependencies = ( 218 | ); 219 | name = FM_ycm; 220 | productName = FM_ycm; 221 | productReference = 798107021892184D00299905 /* FM_ycm.app */; 222 | productType = "com.apple.product-type.application"; 223 | }; 224 | 798107221892184D00299905 /* FM_ycmTests */ = { 225 | isa = PBXNativeTarget; 226 | buildConfigurationList = 798107371892184D00299905 /* Build configuration list for PBXNativeTarget "FM_ycmTests" */; 227 | buildPhases = ( 228 | 7981071F1892184D00299905 /* Sources */, 229 | 798107201892184D00299905 /* Frameworks */, 230 | 798107211892184D00299905 /* Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | 798107291892184D00299905 /* PBXTargetDependency */, 236 | ); 237 | name = FM_ycmTests; 238 | productName = FM_ycmTests; 239 | productReference = 798107231892184D00299905 /* FM_ycmTests.xctest */; 240 | productType = "com.apple.product-type.bundle.unit-test"; 241 | }; 242 | /* End PBXNativeTarget section */ 243 | 244 | /* Begin PBXProject section */ 245 | 798106FA1892184D00299905 /* Project object */ = { 246 | isa = PBXProject; 247 | attributes = { 248 | CLASSPREFIX = FM; 249 | LastUpgradeCheck = 0500; 250 | ORGANIZATIONNAME = yangcaimu; 251 | TargetAttributes = { 252 | 798107221892184D00299905 = { 253 | TestTargetID = 798107011892184D00299905; 254 | }; 255 | }; 256 | }; 257 | buildConfigurationList = 798106FD1892184D00299905 /* Build configuration list for PBXProject "FM_ycm" */; 258 | compatibilityVersion = "Xcode 3.2"; 259 | developmentRegion = English; 260 | hasScannedForEncodings = 0; 261 | knownRegions = ( 262 | en, 263 | Base, 264 | ); 265 | mainGroup = 798106F91892184D00299905; 266 | productRefGroup = 798107031892184D00299905 /* Products */; 267 | projectDirPath = ""; 268 | projectRoot = ""; 269 | targets = ( 270 | 798107011892184D00299905 /* FM_ycm */, 271 | 798107221892184D00299905 /* FM_ycmTests */, 272 | ); 273 | }; 274 | /* End PBXProject section */ 275 | 276 | /* Begin PBXResourcesBuildPhase section */ 277 | 798107001892184D00299905 /* Resources */ = { 278 | isa = PBXResourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | 7981071E1892184D00299905 /* Images.xcassets in Resources */, 282 | 798107101892184D00299905 /* InfoPlist.strings in Resources */, 283 | 798107191892184D00299905 /* Main.storyboard in Resources */, 284 | 79EF948418AB859A004BC175 /* AppUI.png in Resources */, 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | }; 288 | 798107211892184D00299905 /* Resources */ = { 289 | isa = PBXResourcesBuildPhase; 290 | buildActionMask = 2147483647; 291 | files = ( 292 | 7981072F1892184D00299905 /* InfoPlist.strings in Resources */, 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | }; 296 | /* End PBXResourcesBuildPhase section */ 297 | 298 | /* Begin PBXShellScriptBuildPhase section */ 299 | 77DD4015365C4A7093553A7C /* Check Pods Manifest.lock */ = { 300 | isa = PBXShellScriptBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | ); 304 | inputPaths = ( 305 | ); 306 | name = "Check Pods Manifest.lock"; 307 | outputPaths = ( 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | shellPath = /bin/sh; 311 | 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"; 312 | showEnvVarsInLog = 0; 313 | }; 314 | F7B88E0FCD904954881E3E0D /* Copy Pods Resources */ = { 315 | isa = PBXShellScriptBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | ); 319 | inputPaths = ( 320 | ); 321 | name = "Copy Pods Resources"; 322 | outputPaths = ( 323 | ); 324 | runOnlyForDeploymentPostprocessing = 0; 325 | shellPath = /bin/sh; 326 | shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n"; 327 | showEnvVarsInLog = 0; 328 | }; 329 | /* End PBXShellScriptBuildPhase section */ 330 | 331 | /* Begin PBXSourcesBuildPhase section */ 332 | 798106FE1892184D00299905 /* Sources */ = { 333 | isa = PBXSourcesBuildPhase; 334 | buildActionMask = 2147483647; 335 | files = ( 336 | 798107121892184D00299905 /* main.m in Sources */, 337 | 7946C10A18A0B42600E0C692 /* Channel.m in Sources */, 338 | 799F3FBD18A79411003871F8 /* User.m in Sources */, 339 | 798107161892184D00299905 /* FMAppDelegate.m in Sources */, 340 | 799F3FBA18A79300003871F8 /* Model.xcdatamodeld in Sources */, 341 | 7981071C1892184D00299905 /* FMViewController.m in Sources */, 342 | 7946C10D18A10F4B00E0C692 /* LoginViewController.m in Sources */, 343 | 79A8E87718977A39007CF082 /* Track.m in Sources */, 344 | 7946C10618A0AA4500E0C692 /* ChannelsViewController.m in Sources */, 345 | ); 346 | runOnlyForDeploymentPostprocessing = 0; 347 | }; 348 | 7981071F1892184D00299905 /* Sources */ = { 349 | isa = PBXSourcesBuildPhase; 350 | buildActionMask = 2147483647; 351 | files = ( 352 | 798107311892184D00299905 /* FM_ycmTests.m in Sources */, 353 | ); 354 | runOnlyForDeploymentPostprocessing = 0; 355 | }; 356 | /* End PBXSourcesBuildPhase section */ 357 | 358 | /* Begin PBXTargetDependency section */ 359 | 798107291892184D00299905 /* PBXTargetDependency */ = { 360 | isa = PBXTargetDependency; 361 | target = 798107011892184D00299905 /* FM_ycm */; 362 | targetProxy = 798107281892184D00299905 /* PBXContainerItemProxy */; 363 | }; 364 | /* End PBXTargetDependency section */ 365 | 366 | /* Begin PBXVariantGroup section */ 367 | 7981070E1892184D00299905 /* InfoPlist.strings */ = { 368 | isa = PBXVariantGroup; 369 | children = ( 370 | 7981070F1892184D00299905 /* en */, 371 | ); 372 | name = InfoPlist.strings; 373 | sourceTree = ""; 374 | }; 375 | 798107171892184D00299905 /* Main.storyboard */ = { 376 | isa = PBXVariantGroup; 377 | children = ( 378 | 798107181892184D00299905 /* Base */, 379 | ); 380 | name = Main.storyboard; 381 | sourceTree = ""; 382 | }; 383 | 7981072D1892184D00299905 /* InfoPlist.strings */ = { 384 | isa = PBXVariantGroup; 385 | children = ( 386 | 7981072E1892184D00299905 /* en */, 387 | ); 388 | name = InfoPlist.strings; 389 | sourceTree = ""; 390 | }; 391 | /* End PBXVariantGroup section */ 392 | 393 | /* Begin XCBuildConfiguration section */ 394 | 798107321892184D00299905 /* Debug */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | ALWAYS_SEARCH_USER_PATHS = NO; 398 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 399 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 400 | CLANG_CXX_LIBRARY = "libc++"; 401 | CLANG_ENABLE_MODULES = YES; 402 | CLANG_ENABLE_OBJC_ARC = YES; 403 | CLANG_WARN_BOOL_CONVERSION = YES; 404 | CLANG_WARN_CONSTANT_CONVERSION = YES; 405 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 406 | CLANG_WARN_EMPTY_BODY = YES; 407 | CLANG_WARN_ENUM_CONVERSION = YES; 408 | CLANG_WARN_INT_CONVERSION = YES; 409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 410 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 411 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 412 | COPY_PHASE_STRIP = NO; 413 | GCC_C_LANGUAGE_STANDARD = gnu99; 414 | GCC_DYNAMIC_NO_PIC = NO; 415 | GCC_OPTIMIZATION_LEVEL = 0; 416 | GCC_PREPROCESSOR_DEFINITIONS = ( 417 | "DEBUG=1", 418 | "$(inherited)", 419 | ); 420 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 421 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 422 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 423 | GCC_WARN_UNDECLARED_SELECTOR = YES; 424 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 425 | GCC_WARN_UNUSED_FUNCTION = YES; 426 | GCC_WARN_UNUSED_VARIABLE = YES; 427 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 428 | ONLY_ACTIVE_ARCH = YES; 429 | SDKROOT = iphoneos; 430 | }; 431 | name = Debug; 432 | }; 433 | 798107331892184D00299905 /* Release */ = { 434 | isa = XCBuildConfiguration; 435 | buildSettings = { 436 | ALWAYS_SEARCH_USER_PATHS = NO; 437 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 438 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 439 | CLANG_CXX_LIBRARY = "libc++"; 440 | CLANG_ENABLE_MODULES = YES; 441 | CLANG_ENABLE_OBJC_ARC = YES; 442 | CLANG_WARN_BOOL_CONVERSION = YES; 443 | CLANG_WARN_CONSTANT_CONVERSION = YES; 444 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INT_CONVERSION = YES; 448 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 449 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 450 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 451 | COPY_PHASE_STRIP = YES; 452 | ENABLE_NS_ASSERTIONS = NO; 453 | GCC_C_LANGUAGE_STANDARD = gnu99; 454 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 455 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 456 | GCC_WARN_UNDECLARED_SELECTOR = YES; 457 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 458 | GCC_WARN_UNUSED_FUNCTION = YES; 459 | GCC_WARN_UNUSED_VARIABLE = YES; 460 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 461 | SDKROOT = iphoneos; 462 | VALIDATE_PRODUCT = YES; 463 | }; 464 | name = Release; 465 | }; 466 | 798107351892184D00299905 /* Debug */ = { 467 | isa = XCBuildConfiguration; 468 | baseConfigurationReference = 6C05AB7DDF4543A78C0F75A0 /* Pods.xcconfig */; 469 | buildSettings = { 470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 471 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 472 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 473 | GCC_PREFIX_HEADER = "FM_ycm/FM_ycm-Prefix.pch"; 474 | INFOPLIST_FILE = "FM_ycm/FM_ycm-Info.plist"; 475 | LIBRARY_SEARCH_PATHS = ( 476 | "$(inherited)", 477 | "\"$(SRCROOT)\"", 478 | ); 479 | OTHER_LDFLAGS = ( 480 | "-ObjC", 481 | "-framework", 482 | Accelerate, 483 | "-framework", 484 | AudioToolbox, 485 | "-framework", 486 | CFNetwork, 487 | "-framework", 488 | CoreAudio, 489 | "-framework", 490 | CoreGraphics, 491 | "-framework", 492 | MobileCoreServices, 493 | "-framework", 494 | OpenGLES, 495 | "-framework", 496 | QuartzCore, 497 | "-framework", 498 | Security, 499 | "-framework", 500 | SystemConfiguration, 501 | "-all_load", 502 | ); 503 | PRODUCT_NAME = "$(TARGET_NAME)"; 504 | USER_HEADER_SEARCH_PATHS = "${SRCROOT}/**"; 505 | WRAPPER_EXTENSION = app; 506 | }; 507 | name = Debug; 508 | }; 509 | 798107361892184D00299905 /* Release */ = { 510 | isa = XCBuildConfiguration; 511 | baseConfigurationReference = 6C05AB7DDF4543A78C0F75A0 /* Pods.xcconfig */; 512 | buildSettings = { 513 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 514 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 515 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 516 | GCC_PREFIX_HEADER = "FM_ycm/FM_ycm-Prefix.pch"; 517 | INFOPLIST_FILE = "FM_ycm/FM_ycm-Info.plist"; 518 | LIBRARY_SEARCH_PATHS = ( 519 | "$(inherited)", 520 | "\"$(SRCROOT)\"", 521 | ); 522 | OTHER_LDFLAGS = ( 523 | "-ObjC", 524 | "-framework", 525 | Accelerate, 526 | "-framework", 527 | AudioToolbox, 528 | "-framework", 529 | CFNetwork, 530 | "-framework", 531 | CoreAudio, 532 | "-framework", 533 | CoreGraphics, 534 | "-framework", 535 | MobileCoreServices, 536 | "-framework", 537 | OpenGLES, 538 | "-framework", 539 | QuartzCore, 540 | "-framework", 541 | Security, 542 | "-framework", 543 | SystemConfiguration, 544 | "-all_load", 545 | ); 546 | PRODUCT_NAME = "$(TARGET_NAME)"; 547 | USER_HEADER_SEARCH_PATHS = "${SRCROOT}/**"; 548 | WRAPPER_EXTENSION = app; 549 | }; 550 | name = Release; 551 | }; 552 | 798107381892184D00299905 /* Debug */ = { 553 | isa = XCBuildConfiguration; 554 | buildSettings = { 555 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 556 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/FM_ycm.app/FM_ycm"; 557 | FRAMEWORK_SEARCH_PATHS = ( 558 | "$(SDKROOT)/Developer/Library/Frameworks", 559 | "$(inherited)", 560 | "$(DEVELOPER_FRAMEWORKS_DIR)", 561 | ); 562 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 563 | GCC_PREFIX_HEADER = "FM_ycm/FM_ycm-Prefix.pch"; 564 | GCC_PREPROCESSOR_DEFINITIONS = ( 565 | "DEBUG=1", 566 | "$(inherited)", 567 | ); 568 | INFOPLIST_FILE = "FM_ycmTests/FM_ycmTests-Info.plist"; 569 | PRODUCT_NAME = "$(TARGET_NAME)"; 570 | TEST_HOST = "$(BUNDLE_LOADER)"; 571 | WRAPPER_EXTENSION = xctest; 572 | }; 573 | name = Debug; 574 | }; 575 | 798107391892184D00299905 /* Release */ = { 576 | isa = XCBuildConfiguration; 577 | buildSettings = { 578 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 579 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/FM_ycm.app/FM_ycm"; 580 | FRAMEWORK_SEARCH_PATHS = ( 581 | "$(SDKROOT)/Developer/Library/Frameworks", 582 | "$(inherited)", 583 | "$(DEVELOPER_FRAMEWORKS_DIR)", 584 | ); 585 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 586 | GCC_PREFIX_HEADER = "FM_ycm/FM_ycm-Prefix.pch"; 587 | INFOPLIST_FILE = "FM_ycmTests/FM_ycmTests-Info.plist"; 588 | PRODUCT_NAME = "$(TARGET_NAME)"; 589 | TEST_HOST = "$(BUNDLE_LOADER)"; 590 | WRAPPER_EXTENSION = xctest; 591 | }; 592 | name = Release; 593 | }; 594 | /* End XCBuildConfiguration section */ 595 | 596 | /* Begin XCConfigurationList section */ 597 | 798106FD1892184D00299905 /* Build configuration list for PBXProject "FM_ycm" */ = { 598 | isa = XCConfigurationList; 599 | buildConfigurations = ( 600 | 798107321892184D00299905 /* Debug */, 601 | 798107331892184D00299905 /* Release */, 602 | ); 603 | defaultConfigurationIsVisible = 0; 604 | defaultConfigurationName = Release; 605 | }; 606 | 798107341892184D00299905 /* Build configuration list for PBXNativeTarget "FM_ycm" */ = { 607 | isa = XCConfigurationList; 608 | buildConfigurations = ( 609 | 798107351892184D00299905 /* Debug */, 610 | 798107361892184D00299905 /* Release */, 611 | ); 612 | defaultConfigurationIsVisible = 0; 613 | defaultConfigurationName = Release; 614 | }; 615 | 798107371892184D00299905 /* Build configuration list for PBXNativeTarget "FM_ycmTests" */ = { 616 | isa = XCConfigurationList; 617 | buildConfigurations = ( 618 | 798107381892184D00299905 /* Debug */, 619 | 798107391892184D00299905 /* Release */, 620 | ); 621 | defaultConfigurationIsVisible = 0; 622 | defaultConfigurationName = Release; 623 | }; 624 | /* End XCConfigurationList section */ 625 | 626 | /* Begin XCVersionGroup section */ 627 | 799F3FB818A79300003871F8 /* Model.xcdatamodeld */ = { 628 | isa = XCVersionGroup; 629 | children = ( 630 | 799F3FB918A79300003871F8 /* Model.xcdatamodel */, 631 | ); 632 | currentVersion = 799F3FB918A79300003871F8 /* Model.xcdatamodel */; 633 | path = Model.xcdatamodeld; 634 | sourceTree = ""; 635 | versionGroupType = wrapper.xcdatamodel; 636 | }; 637 | /* End XCVersionGroup section */ 638 | }; 639 | rootObject = 798106FA1892184D00299905 /* Project object */; 640 | } 641 | -------------------------------------------------------------------------------- /FM_ycm.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FM_ycm/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 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 | 71 | 81 | 94 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | -------------------------------------------------------------------------------- /FM_ycm/CONSTANTS.h: -------------------------------------------------------------------------------- 1 | // 2 | // CONSTANTS.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-4. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #ifndef FM_ycm_CONSTANTS_h 10 | #define FM_ycm_CONSTANTS_h 11 | 12 | 13 | 14 | #endif 15 | 16 | //user login info 17 | #define kUserid @"user_id" 18 | #define kToken @"token" 19 | #define kExpire @"expire" 20 | #define kUserName @"user_name" 21 | 22 | 23 | #define kErrorCode @"r" 24 | #define kChannelId @"channel_id" 25 | #define kChannelName @"channel_name" 26 | 27 | 28 | //load songs type , n-> return a new song list 29 | // s-> next song 30 | // b-> do not play this song again 31 | // r-> rate this song 32 | // u-> unrate this song 33 | 34 | #define kLoadSongsTypeNew @"n" 35 | #define kLoadSongsTypeSkip @"s" 36 | #define kLoadSongsTypeBye @"b" 37 | #define kLoadSongsTypeRate @"r" 38 | #define kLoadSongsTypeUnrate @"u" 39 | -------------------------------------------------------------------------------- /FM_ycm/Channel.h: -------------------------------------------------------------------------------- 1 | // 2 | // Channel.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-4. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Channel : NSObject 12 | 13 | @property(nonatomic,strong)NSString *name; 14 | @property(nonatomic,strong)NSString *channel_id; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /FM_ycm/Channel.m: -------------------------------------------------------------------------------- 1 | // 2 | // Channel.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-4. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import "Channel.h" 10 | 11 | @implementation Channel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /FM_ycm/ChannelsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChannelsViewController.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-4. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Channel.h" 11 | @class ChannelsViewController; 12 | 13 | @protocol ChannelsViewControllerDelegate 14 | 15 | -(void)ChannelsViewControllerDidSelect:(ChannelsViewController *)controller didChannel:(Channel *)selectChannel; 16 | 17 | @end 18 | 19 | @interface ChannelsViewController : UITableViewController 20 | 21 | @property (nonatomic,strong) id delegate; 22 | @property (nonatomic,strong) NSMutableArray *channels; 23 | @property (nonatomic,strong) Channel *channel; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /FM_ycm/ChannelsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ChannelsViewController.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-4. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import "ChannelsViewController.h" 10 | #import "Channel.h" 11 | 12 | @interface ChannelsViewController () 13 | 14 | @end 15 | 16 | @implementation ChannelsViewController 17 | 18 | - (id)initWithStyle:(UITableViewStyle)style 19 | { 20 | self = [super initWithStyle:style]; 21 | if (self) { 22 | // Custom initialization 23 | } 24 | return self; 25 | } 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | // Uncomment the following line to preserve selection between presentations. 31 | // self.clearsSelectionOnViewWillAppear = NO; 32 | 33 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 34 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 35 | } 36 | 37 | - (void)didReceiveMemoryWarning 38 | { 39 | [super didReceiveMemoryWarning]; 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | #pragma mark - Table view data source 44 | 45 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 46 | { 47 | // Return the number of sections. 48 | return 1; 49 | } 50 | 51 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 52 | { 53 | // Return the number of rows in the section. 54 | return [self.channels count]; 55 | } 56 | 57 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 58 | { 59 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Channels"]; 60 | self.channel=[self.channels objectAtIndex:indexPath.row]; 61 | cell.textLabel.text=self.channel.name; 62 | return cell; 63 | } 64 | 65 | #pragma mark - UITableViewDelegate method 66 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 67 | self.channel=[self.channels objectAtIndex:indexPath.row]; 68 | [self.delegate ChannelsViewControllerDidSelect:self didChannel:self.channel]; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /FM_ycm/FMAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMAppDelegate.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-1-24. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FMAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /FM_ycm/FMAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMAppDelegate.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-1-24. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import "FMAppDelegate.h" 10 | 11 | @implementation FMAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | NSLog(@"method[applicationDidEnterBackground:] is called"); 28 | } 29 | 30 | - (void)applicationWillEnterForeground:(UIApplication *)application 31 | { 32 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | - (void)applicationDidBecomeActive:(UIApplication *)application 36 | { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | - (void)applicationWillTerminate:(UIApplication *)application 41 | { 42 | 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /FM_ycm/FMViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMViewController.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-1-24. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LoginViewController.h" 11 | #import "ChannelsViewController.h" 12 | 13 | @interface FMViewController : UIViewController 14 | 15 | //控件 16 | @property (strong, nonatomic) IBOutlet UIImageView *imageView; 17 | @property (strong, nonatomic) IBOutlet UIView *audioVisualizerView; 18 | @property (strong, nonatomic) IBOutlet UILabel *songTitle; 19 | @property (strong, nonatomic) IBOutlet UISlider *progress; 20 | @property (strong, nonatomic) IBOutlet UIButton *playing; 21 | @property (strong, nonatomic) IBOutlet UIButton *unLove; 22 | @property (strong, nonatomic) IBOutlet UISlider *sliderVolume; 23 | 24 | //Core Data store 25 | @property (strong, nonatomic, readonly) NSManagedObjectContext *managedObjectContext; 26 | @property (strong, nonatomic, readonly) NSManagedObjectModel *managedObjectModel; 27 | @property (strong, nonatomic, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator; 28 | 29 | 30 | - (IBAction)playingAction:(id)sender; 31 | - (IBAction)nextAction:(id)sender; 32 | - (IBAction)downloadAction:(id)sender; 33 | - (IBAction)loveAction:(id)sender; 34 | - (IBAction)progressAction:(id)sender; 35 | - (IBAction)VolumeAction:(id)sender; 36 | //- (void)saveContext; 37 | - (NSURL *)applicationDocumentsDirectory; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /FM_ycm/FMViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMViewController.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-1-24. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import "FMViewController.h" 10 | #import "AFNetworking.h" 11 | #import "DOUAudioStreamer.h" 12 | #import "DOUAudioStreamer+Options.h" 13 | #import "Track.h" 14 | #import "LoginViewController.h" 15 | #import "Channel.h" 16 | #import "ChannelsViewController.h" 17 | #import "User.h" 18 | 19 | @interface FMViewController () 20 | 21 | @end 22 | 23 | @implementation FMViewController{ 24 | NSMutableArray *tracks; 25 | DOUAudioStreamer *streamer; 26 | NSInteger currentIndex; 27 | Track *track; 28 | NSMutableArray *channels; 29 | Channel *channel; 30 | NSMutableDictionary *songParameters; 31 | NSMutableDictionary *loginParameters; 32 | NSDictionary *loginMess; 33 | BOOL isLogin; 34 | } 35 | 36 | @synthesize managedObjectContext =__managedObjectContext; 37 | @synthesize managedObjectModel = __managedObjectModel; 38 | @synthesize persistentStoreCoordinator = __persistentStoreCoordinator; 39 | 40 | - (void)viewDidLoad 41 | { 42 | [super viewDidLoad]; 43 | [self initAllValue]; 44 | } 45 | 46 | 47 | -(void)initAllValue{ 48 | //初始化所有值 49 | currentIndex=0; 50 | [self.progress setValue:0.0f]; 51 | [self.sliderVolume setValue:[DOUAudioStreamer volume]]; 52 | 53 | //设置音乐进度条 54 | [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(setSliderValue) userInfo:nil repeats:YES]; 55 | 56 | //Get、Post参数 57 | songParameters=[NSMutableDictionary dictionaryWithObjectsAndKeys:@"radio_desktop_win",@"app_name", @"100",@"version",@"n",@"type",@"4",@"channel",nil]; 58 | loginParameters=[NSMutableDictionary dictionaryWithObjectsAndKeys:@"radio_desktop_win",@"app_name", 59 | @"100",@"version", nil]; 60 | 61 | //获取歌曲列表、频道列表 62 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 63 | [self getTracks]; 64 | [self getChannels]; 65 | }); 66 | 67 | //歌曲图片以圆形呈现 68 | self.imageView.layer.masksToBounds = YES; 69 | self.imageView.layer.cornerRadius = 125; 70 | 71 | //歌曲图片增加单击事件 72 | UITapGestureRecognizer *singTapShow=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onClickImageShow)]; 73 | [self.imageView addGestureRecognizer:singTapShow]; 74 | UITapGestureRecognizer *singTapHidden=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onClickImageHidden)]; 75 | [self.audioVisualizerView addGestureRecognizer:singTapHidden]; 76 | 77 | //取得上次登陆成功与否 78 | isLogin = [[NSUserDefaults standardUserDefaults] boolForKey:@"isLogin"]; 79 | if (isLogin) { 80 | NSArray *fetchedObjects = [self userDataFetchRequest]; 81 | for (User *user in fetchedObjects) { 82 | [loginParameters setObject:user.email forKey:@"email"]; 83 | [loginParameters setObject:user.password forKey:@"password"]; 84 | } 85 | [self getLogin:nil]; 86 | } 87 | } 88 | 89 | - (void)didReceiveMemoryWarning 90 | { 91 | [super didReceiveMemoryWarning]; 92 | } 93 | 94 | #pragma mark - songImage singTap 95 | 96 | -(void)onClickImageShow{ 97 | [self.audioVisualizerView setHidden:NO]; 98 | } 99 | 100 | -(void)onClickImageHidden{ 101 | [self.audioVisualizerView setHidden:YES]; 102 | } 103 | 104 | #pragma mark - Tracks methods 105 | 106 | -(void)getTracks{ 107 | NSString *url=@"http://douban.fm/j/app/radio/people"; 108 | AFHTTPSessionManager *manager=[AFHTTPSessionManager manager]; 109 | NSLog(@"current channel--->%@",[songParameters objectForKey:@"channel"]); 110 | [manager GET:url parameters:songParameters success:^(NSURLSessionDataTask *task, id responseObject) { 111 | NSDictionary *responseSongs=[responseObject objectForKey:@"song"]; 112 | if (tracks != nil) { 113 | [tracks removeAllObjects]; 114 | } 115 | tracks=[NSMutableArray array]; 116 | for (NSDictionary *song in responseSongs) { 117 | //依次赋值给track 118 | track=[[Track alloc] init]; 119 | track.artist=[song objectForKey:@"artist"]; 120 | track.title=[song objectForKey:@"title"]; 121 | track.sid=[song objectForKey:@"sid"]; 122 | track.url=[NSURL URLWithString:[song objectForKey:@"url"]]; 123 | track.picture=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[song objectForKey:@"picture"]]]]; 124 | [tracks addObject:track]; 125 | } 126 | int a=0; 127 | for (Track *temp in tracks) { 128 | a++; 129 | NSLog(@"temp[%d]%@",a,temp.title); 130 | } 131 | //读取获得的Tracks 132 | [self loadTracks]; 133 | NSLog(@"get Tracks success"); 134 | } failure:^(NSURLSessionDataTask *task, NSError *error) { 135 | NSLog(@"[getTracks]Network connect failure:error--->%@",error); 136 | }]; 137 | } 138 | 139 | -(void)loadTracks{ 140 | [self removeObserverForStreamer]; 141 | track=[tracks objectAtIndex:currentIndex]; 142 | streamer=[DOUAudioStreamer streamerWithAudioFile:track]; 143 | [streamer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; 144 | [self setSliderValue]; 145 | NSString *title=[NSString stringWithFormat:@"%@--%@",track.title,track.artist]; 146 | [self.songTitle setText:title]; 147 | [self.imageView setImage:[track picture]]; 148 | [streamer play]; 149 | } 150 | 151 | -(void)removeObserverForStreamer{ 152 | if (streamer != nil) { 153 | [streamer removeObserver:self forKeyPath:@"status"]; 154 | streamer=nil; 155 | } 156 | } 157 | 158 | -(BOOL)reGetTracks{ 159 | if (currentIndex == [tracks count]-1 ) { 160 | currentIndex=0; 161 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 162 | [self getTracks]; 163 | }); 164 | return NO; 165 | }else{ 166 | return YES; 167 | } 168 | } 169 | 170 | #pragma mark - Channels method 171 | -(void)getChannels{ 172 | NSString *url=@"http://douban.fm/j/app/radio/channels"; 173 | AFHTTPSessionManager *manager=[AFHTTPSessionManager manager]; 174 | if (channels != nil) { 175 | channels = nil; 176 | } 177 | [manager GET:url parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) { 178 | NSDictionary *responseChannels=[responseObject objectForKey:@"channels"]; 179 | channels=[NSMutableArray array]; 180 | for (NSDictionary *dicChannels in responseChannels) { 181 | //依次赋值给channel 182 | channel=[[Channel alloc] init]; 183 | channel.name=[dicChannels objectForKey:@"name"]; 184 | channel.channel_id=[dicChannels objectForKey:@"channel_id"]; 185 | [channels addObject:channel]; 186 | } 187 | NSLog(@"get Channels success"); 188 | } failure:^(NSURLSessionDataTask *task, NSError *error) { 189 | NSLog(@"[getChannels]Network connect failure:error--->%@",error); 190 | }]; 191 | } 192 | 193 | #pragma mark - ChannelsViewControllerDelegate method 194 | -(void)ChannelsViewControllerDidSelect:(ChannelsViewController *)controller didChannel:(Channel *)selectChannel{ 195 | NSLog(@"channel_id--->name:%@--->%@",selectChannel.channel_id,selectChannel.name); 196 | [songParameters setValue:selectChannel.channel_id forKey:@"channel"]; 197 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 198 | [self getTracks]; 199 | }); 200 | [self dismissViewControllerAnimated:YES completion:nil]; 201 | } 202 | 203 | #pragma mark - Login method 204 | -(void)getLogin:(LoginViewController *)controller{ 205 | 206 | NSString *url=@"http://www.douban.com/j/app/login"; 207 | AFHTTPSessionManager *manager=[AFHTTPSessionManager manager]; 208 | [manager POST:url parameters:loginParameters success:^(NSURLSessionDataTask *task, id responseObject) { 209 | loginMess=(NSDictionary *)responseObject; 210 | 211 | if ( [[[loginMess objectForKey:@"r"] stringValue] isEqualToString:@"0"] ) { 212 | //登陆成功 213 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isLogin"]; 214 | [songParameters setObject:[loginMess objectForKey:@"user_id"] forKey:@"user_id"]; 215 | [songParameters setObject:[loginMess objectForKey:@"expire"] forKey:@"expire"]; 216 | [songParameters setObject:[loginMess objectForKey:@"token"] forKey:@"token"]; 217 | [self.navigationItem setTitle:[loginMess objectForKey:@"user_name"]]; 218 | [self deleteCoreData]; 219 | [self insertCoreData]; 220 | [self.navigationController popViewControllerAnimated:YES]; 221 | NSLog(@"login success"); 222 | 223 | }else if ( [[[loginMess objectForKey:@"r"] stringValue] isEqualToString:@"1"] ){ 224 | //登陆失败 225 | [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isLogin"]; 226 | [self deleteCoreData]; 227 | UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Login failure" message:[NSString stringWithFormat:@"%@",[loginMess objectForKey:@"err"]] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; 228 | [alert show]; 229 | [controller.nameText setText:@""]; 230 | [controller.passwordText setText:@""]; 231 | NSLog(@"login failure"); 232 | } 233 | } failure:^(NSURLSessionDataTask *task, NSError *error) { 234 | //网络连接失败 235 | [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isLogin"]; 236 | NSLog(@"[getLogin]Network connect failure:error--->%@",error); 237 | }]; 238 | } 239 | 240 | #pragma mark - LoginViewControllerDelegate method 241 | 242 | -(void)loginViewControllerDidCancel:(LoginViewController *)controller{ 243 | [self.navigationController popViewControllerAnimated:YES]; 244 | } 245 | 246 | -(void)loginViewControllerDidSave:(LoginViewController *)controller{ 247 | if (controller.nameText.text.length != 0 && controller.passwordText.text.length != 0) { 248 | [loginParameters setObject:controller.nameText.text forKey:@"email"]; 249 | [loginParameters setObject:controller.passwordText.text forKey:@"password"]; 250 | [self getLogin:controller]; 251 | }else{ 252 | UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Login failure" message:@"Please enter the email address and password" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; 253 | [alert show]; 254 | } 255 | } 256 | 257 | #pragma mark - CoreData store 258 | //- (void)saveContext{ 259 | // NSLog(@"method[saveContext] is called"); 260 | // NSError *error=nil; 261 | // NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 262 | // if (managedObjectContext != nil) { 263 | // if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 264 | // NSLog(@"Unresolved error %@, %@",error,[error userInfo]); 265 | // abort(); 266 | // } 267 | // } 268 | //} 269 | 270 | - (NSURL *)applicationDocumentsDirectory{ 271 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 272 | } 273 | 274 | - (NSManagedObjectContext *)managedObjectContext{ 275 | if (__managedObjectContext != nil) { 276 | return __managedObjectContext; 277 | } 278 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 279 | if (coordinator != nil) { 280 | __managedObjectContext = [[NSManagedObjectContext alloc] init]; 281 | [__managedObjectContext setPersistentStoreCoordinator:coordinator]; 282 | } 283 | return __managedObjectContext; 284 | } 285 | 286 | - (NSManagedObjectModel *) managedObjectModel{ 287 | if (__managedObjectModel != nil) { 288 | return __managedObjectModel; 289 | } 290 | NSURL *modeURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"]; 291 | __managedObjectModel=[[NSManagedObjectModel alloc] initWithContentsOfURL:modeURL]; 292 | return __managedObjectModel; 293 | } 294 | 295 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator{ 296 | if (__persistentStoreCoordinator != nil) { 297 | return __persistentStoreCoordinator; 298 | } 299 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Model.sqlite"]; 300 | NSError *error; 301 | __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 302 | if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 303 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 304 | abort(); 305 | } 306 | return __persistentStoreCoordinator; 307 | } 308 | 309 | - (void)insertCoreData{ 310 | NSManagedObjectContext *context = [self managedObjectContext]; 311 | User *user=[NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:context]; 312 | if ( [[loginParameters objectForKey:@"email"] length] != 0 && [[loginParameters objectForKey:@"password"] length] != 0) { 313 | user.email=[loginParameters objectForKey:@"email"]; 314 | user.password=[loginParameters objectForKey:@"password"]; 315 | NSError *error; 316 | if (![context save:&error]) { 317 | NSLog(@"不能保存:%@",[error localizedDescription]); 318 | } 319 | } 320 | } 321 | 322 | - (void)deleteCoreData{ 323 | NSError *error; 324 | NSManagedObjectContext *context = [self managedObjectContext]; 325 | NSArray *fetchedObjects = [self userDataFetchRequest]; 326 | if ( fetchedObjects != nil) { 327 | for (User *user in fetchedObjects) { 328 | for (NSManagedObject *obj in fetchedObjects) { 329 | [context deleteObject:obj]; 330 | } 331 | if (![context save:&error]) { 332 | NSLog(@"error:%@",error); 333 | } 334 | } 335 | } 336 | } 337 | 338 | - (NSArray *)userDataFetchRequest{ 339 | NSManagedObjectContext *context = [self managedObjectContext]; 340 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 341 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:context]; 342 | [fetchRequest setEntity:entity]; 343 | NSError *error; 344 | NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; 345 | if ( fetchedObjects != nil ) { 346 | NSLog(@"[fetchedObjects count]--->%d",[fetchedObjects count]); 347 | for (User *user in fetchedObjects) { 348 | [loginParameters setObject:user.email forKey:@"email"]; 349 | [loginParameters setObject:user.password forKey:@"password"]; 350 | } 351 | } 352 | return fetchedObjects; 353 | } 354 | 355 | #pragma mark - KVO delegate method 356 | 357 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ 358 | if ([keyPath isEqualToString:@"status"] ) { 359 | if ([streamer status] == DOUAudioStreamerFinished){ 360 | [self performSelector:@selector(nextAction:) 361 | onThread:[NSThread mainThread] 362 | withObject:nil 363 | waitUntilDone:NO]; 364 | } 365 | } 366 | } 367 | 368 | -(void)setSliderValue{ 369 | if (streamer.duration == 0.0) { 370 | [self.progress setValue:0.0f animated:NO]; 371 | }else{ 372 | [self.progress setValue:[streamer currentTime] / [streamer duration] animated:YES]; 373 | } 374 | } 375 | 376 | #pragma mark - segue method 377 | -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ 378 | if ([segue.identifier isEqualToString:@"login"]) { 379 | LoginViewController *loginvc=(LoginViewController *)segue.destinationViewController; 380 | loginvc.delegate=self; 381 | } 382 | if ([segue.identifier isEqualToString:@"channels"]) { 383 | ChannelsViewController *chvc=(ChannelsViewController *)segue.destinationViewController; 384 | chvc.channels=channels; 385 | chvc.delegate=self; 386 | } 387 | } 388 | 389 | #pragma mark - action method 390 | /* 391 | DOUAudioStreamerPlaying, 392 | DOUAudioStreamerPaused, 393 | DOUAudioStreamerIdle, 394 | DOUAudioStreamerFinished, 395 | DOUAudioStreamerBuffering, 396 | DOUAudioStreamerError 397 | */ 398 | - (IBAction)playingAction:(id)sender { 399 | if ([streamer status] == DOUAudioStreamerPaused || [streamer status] == DOUAudioStreamerIdle) { 400 | [streamer play]; 401 | [self.playing setTitle:@"Pause" forState:UIControlStateNormal]; 402 | }else{ 403 | [streamer pause]; 404 | [self.playing setTitle:@"play" forState:UIControlStateNormal]; 405 | } 406 | } 407 | 408 | - (IBAction)nextAction:(id)sender { 409 | [self.unLove setTitle:@"unLove" forState:UIControlStateNormal]; 410 | if ([self reGetTracks]) { 411 | currentIndex++; 412 | [self loadTracks]; 413 | } 414 | } 415 | 416 | - (IBAction)downloadAction:(id)sender { 417 | 418 | } 419 | 420 | - (IBAction)loveAction:(id)sender { 421 | NSString *loveURL=@"http://douban.fm/j/app/radio/people"; 422 | NSMutableDictionary *loveParameters=[NSMutableDictionary dictionaryWithObjectsAndKeys:@"radio_desktop_win",@"app_name", @"100",@"version",@"n",@"type",@"4",@"channel",nil]; 423 | [loveParameters setObject:@"r" forKey:@"type"]; 424 | [loveParameters setObject:track.sid forKey:@"sid"]; 425 | if (loginMess != nil) { 426 | [loveParameters setObject:[loginMess objectForKey:@"user_id"] forKey:@"user_id"]; 427 | [loveParameters setObject:[loginMess objectForKey:@"expire"] forKey:@"expire"]; 428 | [loveParameters setObject:[loginMess objectForKey:@"token"] forKey:@"token"]; 429 | } 430 | AFHTTPSessionManager *loveManager=[AFHTTPSessionManager manager]; 431 | [loveManager GET:loveURL parameters:loveParameters success:^(NSURLSessionDataTask *task, id responseObject) { 432 | [self.unLove setTitle:@"Love" forState:UIControlStateNormal]; 433 | NSLog(@"Love is success"); 434 | } failure:^(NSURLSessionDataTask *task, NSError *error) { 435 | NSLog(@"error%@",error); 436 | }]; 437 | 438 | } 439 | 440 | - (IBAction)progressAction:(id)sender { 441 | [self.progress setValue:self.progress.value animated:YES]; 442 | [streamer setCurrentTime:[streamer duration] * [self.progress value]]; 443 | } 444 | 445 | - (IBAction)VolumeAction:(id)sender { 446 | [DOUAudioStreamer setVolume:self.sliderVolume.value]; 447 | } 448 | @end 449 | -------------------------------------------------------------------------------- /FM_ycm/FM_ycm-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | yangcaimu.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /FM_ycm/FM_ycm-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #import 17 | #import "CONSTANTS.h" 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/0.imageset/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/0.imageset/0.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "0.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/1.imageset/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/1.imageset/1.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "1.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/10.imageset/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/10.imageset/10.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "10.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/11.imageset/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/11.imageset/11.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "11.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/12.imageset/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/12.imageset/12.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "12.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/13.imageset/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/13.imageset/13.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "13.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/2.imageset/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/2.imageset/2.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "2.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/3.imageset/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/3.imageset/3.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "3.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/4.imageset/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/4.imageset/4.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "4.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/5.imageset/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/5.imageset/5.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "5.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/6.imageset/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/6.imageset/6.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "6.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/7.imageset/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/7.imageset/7.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "7.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/8.imageset/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/8.imageset/8.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "8.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/9.imageset/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LavareX/DoubanFM/99f2adc7b4b04a88e34a8d20afc8e171d0906bd9/FM_ycm/Images.xcassets/png/9.imageset/9.png -------------------------------------------------------------------------------- /FM_ycm/Images.xcassets/png/9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "9.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /FM_ycm/LoginViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-4. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class LoginViewController; 12 | 13 | @protocol LoginViewControllerDelegate 14 | 15 | -(void)loginViewControllerDidCancel:(LoginViewController *)controller; 16 | -(void)loginViewControllerDidSave:(LoginViewController *)controller; 17 | 18 | @end 19 | 20 | @interface LoginViewController : UITableViewController 21 | 22 | @property(nonatomic,strong) id delegate; 23 | @property (strong, nonatomic) IBOutlet UITextField *nameText; 24 | @property (strong, nonatomic) IBOutlet UITextField *passwordText; 25 | @property (strong, nonatomic) IBOutlet UIButton *loginButton; 26 | 27 | 28 | - (IBAction)cancelAction:(id)sender; 29 | - (IBAction)loginAction:(id)sender; 30 | - (IBAction)TextField_DidEndOnExit:(UITextField *)sender; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /FM_ycm/LoginViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-4. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import "LoginViewController.h" 10 | 11 | @interface LoginViewController () 12 | 13 | @end 14 | 15 | @implementation LoginViewController{ 16 | 17 | } 18 | 19 | - (id)initWithStyle:(UITableViewStyle)style 20 | { 21 | self = [super initWithStyle:style]; 22 | if (self) { 23 | // Custom initialization 24 | } 25 | return self; 26 | } 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | 32 | // Uncomment the following line to preserve selection between presentations. 33 | // self.clearsSelectionOnViewWillAppear = NO; 34 | 35 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 36 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 37 | } 38 | 39 | - (void)didReceiveMemoryWarning 40 | { 41 | [super didReceiveMemoryWarning]; 42 | // Dispose of any resources that can be recreated. 43 | } 44 | 45 | #pragma mark - UITableViewDelegate method 46 | 47 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 48 | if (indexPath.section == 0) { 49 | [self.nameText becomeFirstResponder]; 50 | }else if (indexPath.section == 1){ 51 | [self.passwordText becomeFirstResponder]; 52 | } 53 | } 54 | 55 | #pragma mark - Action method 56 | 57 | - (IBAction)cancelAction:(id)sender { 58 | [self.delegate loginViewControllerDidCancel:self]; 59 | } 60 | 61 | - (IBAction)loginAction:(id)sender { 62 | [self.delegate loginViewControllerDidSave:self]; 63 | } 64 | 65 | - (IBAction)TextField_DidEndOnExit:(UITextField *)sender{ 66 | if (sender.tag == 100) { 67 | [self.passwordText becomeFirstResponder]; 68 | }else if (sender.tag == 200){ 69 | [self.passwordText resignFirstResponder]; 70 | [self.loginButton sendActionsForControlEvents:UIControlEventTouchUpInside]; 71 | } 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /FM_ycm/Model.xcdatamodeld/Model.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /FM_ycm/Track.h: -------------------------------------------------------------------------------- 1 | // 2 | // Track.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-1-28. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DOUAudioStreamer.h" 11 | 12 | @interface Track : NSObject 13 | 14 | @property (nonatomic,strong) NSString *artist; 15 | @property (nonatomic,strong) NSString *title; 16 | @property (nonatomic,strong) NSString *sid; 17 | @property (nonatomic,strong) NSURL *url; 18 | @property (nonatomic,strong) UIImage *picture; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /FM_ycm/Track.m: -------------------------------------------------------------------------------- 1 | // 2 | // Track.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-1-28. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import "Track.h" 10 | 11 | @implementation Track 12 | 13 | - (NSURL *)audioFileURL{ 14 | return [self url]; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /FM_ycm/User.h: -------------------------------------------------------------------------------- 1 | // 2 | // User.h 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-9. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface User : NSManagedObject 14 | 15 | @property (nonatomic, retain) NSString * email; 16 | @property (nonatomic, retain) NSString * password; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /FM_ycm/User.m: -------------------------------------------------------------------------------- 1 | // 2 | // User.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-2-9. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import "User.h" 10 | 11 | 12 | @implementation User 13 | 14 | @dynamic email; 15 | @dynamic password; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /FM_ycm/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /FM_ycm/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // FM_ycm 4 | // 5 | // Created by yangcaimu on 14-1-24. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "FMAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([FMAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /FM_ycmTests/FM_ycmTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | yangcaimu.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /FM_ycmTests/FM_ycmTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // FM_ycmTests.m 3 | // FM_ycmTests 4 | // 5 | // Created by yangcaimu on 14-1-24. 6 | // Copyright (c) 2014年 yangcaimu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FM_ycmTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation FM_ycmTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /FM_ycmTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DoubanFM 2 | ======== 3 | 4 | 豆瓣FM iOS版 5 | 6 | 7 | 功能:在线听歌,有不同的频道供选择,登陆豆瓣账号还可以听私人频道,对喜欢的歌曲加心, 8 | 支持账号自动登陆,在上次登陆成功的情况下 9 | 10 | ![AppUI](http://ww2.sinaimg.cn/mw690/68f6b8ecgw1edhj8a9amuj20b40jqq46.jpg) 11 | 12 | Lib: 13 | AFNetworking---->网络通信、解析JSON; 14 | DOUAudioStreamer---->音频解析; 15 | CocoaPods---->依赖管理 16 | 17 | API: 18 | 豆瓣FM API 19 | --------------------------------------------------------------------------------