├── DemoAVPlayer.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── wutian.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── wutian.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── DemoAVPlayer.xcscheme │ └── xcschememanagement.plist ├── DemoAVPlayer ├── AppDelegate.h ├── AppDelegate.m ├── AssetLoaderDelegate.h ├── AssetLoaderDelegate.m ├── AssetLoaderProtocol.h ├── AssetLoaderProtocol.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m └── README.md /DemoAVPlayer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C61879561BDDF21200F4D23D /* AssetLoaderProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = C61879551BDDF21200F4D23D /* AssetLoaderProtocol.m */; }; 11 | C67C4DF41BDA086200F17CFD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C67C4DF31BDA086200F17CFD /* main.m */; }; 12 | C67C4DF71BDA086200F17CFD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C67C4DF61BDA086200F17CFD /* AppDelegate.m */; }; 13 | C67C4DFA1BDA086200F17CFD /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C67C4DF91BDA086200F17CFD /* ViewController.m */; }; 14 | C67C4DFD1BDA086200F17CFD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C67C4DFB1BDA086200F17CFD /* Main.storyboard */; }; 15 | C67C4DFF1BDA086200F17CFD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C67C4DFE1BDA086200F17CFD /* Assets.xcassets */; }; 16 | C67C4E021BDA086200F17CFD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C67C4E001BDA086200F17CFD /* LaunchScreen.storyboard */; }; 17 | C67C4E0B1BDA08FA00F17CFD /* AssetLoaderDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C67C4E0A1BDA08FA00F17CFD /* AssetLoaderDelegate.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | C61879541BDDF21200F4D23D /* AssetLoaderProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssetLoaderProtocol.h; sourceTree = ""; }; 22 | C61879551BDDF21200F4D23D /* AssetLoaderProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AssetLoaderProtocol.m; sourceTree = ""; }; 23 | C67C4DEF1BDA086200F17CFD /* DemoAVPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoAVPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | C67C4DF31BDA086200F17CFD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | C67C4DF51BDA086200F17CFD /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | C67C4DF61BDA086200F17CFD /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | C67C4DF81BDA086200F17CFD /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | C67C4DF91BDA086200F17CFD /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | C67C4DFC1BDA086200F17CFD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | C67C4DFE1BDA086200F17CFD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | C67C4E011BDA086200F17CFD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | C67C4E031BDA086200F17CFD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | C67C4E091BDA08FA00F17CFD /* AssetLoaderDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssetLoaderDelegate.h; sourceTree = ""; }; 34 | C67C4E0A1BDA08FA00F17CFD /* AssetLoaderDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AssetLoaderDelegate.m; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | C67C4DEC1BDA086200F17CFD /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | C67C4DE61BDA086200F17CFD = { 49 | isa = PBXGroup; 50 | children = ( 51 | C67C4DF11BDA086200F17CFD /* DemoAVPlayer */, 52 | C67C4DF01BDA086200F17CFD /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | C67C4DF01BDA086200F17CFD /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | C67C4DEF1BDA086200F17CFD /* DemoAVPlayer.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | C67C4DF11BDA086200F17CFD /* DemoAVPlayer */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | C67C4DF51BDA086200F17CFD /* AppDelegate.h */, 68 | C67C4DF61BDA086200F17CFD /* AppDelegate.m */, 69 | C67C4E091BDA08FA00F17CFD /* AssetLoaderDelegate.h */, 70 | C67C4E0A1BDA08FA00F17CFD /* AssetLoaderDelegate.m */, 71 | C61879541BDDF21200F4D23D /* AssetLoaderProtocol.h */, 72 | C61879551BDDF21200F4D23D /* AssetLoaderProtocol.m */, 73 | C67C4DF81BDA086200F17CFD /* ViewController.h */, 74 | C67C4DF91BDA086200F17CFD /* ViewController.m */, 75 | C67C4DFB1BDA086200F17CFD /* Main.storyboard */, 76 | C67C4DFE1BDA086200F17CFD /* Assets.xcassets */, 77 | C67C4E001BDA086200F17CFD /* LaunchScreen.storyboard */, 78 | C67C4E031BDA086200F17CFD /* Info.plist */, 79 | C67C4DF21BDA086200F17CFD /* Supporting Files */, 80 | ); 81 | path = DemoAVPlayer; 82 | sourceTree = ""; 83 | }; 84 | C67C4DF21BDA086200F17CFD /* Supporting Files */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | C67C4DF31BDA086200F17CFD /* main.m */, 88 | ); 89 | name = "Supporting Files"; 90 | sourceTree = ""; 91 | }; 92 | /* End PBXGroup section */ 93 | 94 | /* Begin PBXNativeTarget section */ 95 | C67C4DEE1BDA086200F17CFD /* DemoAVPlayer */ = { 96 | isa = PBXNativeTarget; 97 | buildConfigurationList = C67C4E061BDA086200F17CFD /* Build configuration list for PBXNativeTarget "DemoAVPlayer" */; 98 | buildPhases = ( 99 | C67C4DEB1BDA086200F17CFD /* Sources */, 100 | C67C4DEC1BDA086200F17CFD /* Frameworks */, 101 | C67C4DED1BDA086200F17CFD /* Resources */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = DemoAVPlayer; 108 | productName = DemoAVPlayer; 109 | productReference = C67C4DEF1BDA086200F17CFD /* DemoAVPlayer.app */; 110 | productType = "com.apple.product-type.application"; 111 | }; 112 | /* End PBXNativeTarget section */ 113 | 114 | /* Begin PBXProject section */ 115 | C67C4DE71BDA086200F17CFD /* Project object */ = { 116 | isa = PBXProject; 117 | attributes = { 118 | LastUpgradeCheck = 0700; 119 | ORGANIZATIONNAME = Wutian; 120 | TargetAttributes = { 121 | C67C4DEE1BDA086200F17CFD = { 122 | CreatedOnToolsVersion = 7.0.1; 123 | }; 124 | }; 125 | }; 126 | buildConfigurationList = C67C4DEA1BDA086200F17CFD /* Build configuration list for PBXProject "DemoAVPlayer" */; 127 | compatibilityVersion = "Xcode 3.2"; 128 | developmentRegion = English; 129 | hasScannedForEncodings = 0; 130 | knownRegions = ( 131 | en, 132 | Base, 133 | ); 134 | mainGroup = C67C4DE61BDA086200F17CFD; 135 | productRefGroup = C67C4DF01BDA086200F17CFD /* Products */; 136 | projectDirPath = ""; 137 | projectRoot = ""; 138 | targets = ( 139 | C67C4DEE1BDA086200F17CFD /* DemoAVPlayer */, 140 | ); 141 | }; 142 | /* End PBXProject section */ 143 | 144 | /* Begin PBXResourcesBuildPhase section */ 145 | C67C4DED1BDA086200F17CFD /* Resources */ = { 146 | isa = PBXResourcesBuildPhase; 147 | buildActionMask = 2147483647; 148 | files = ( 149 | C67C4E021BDA086200F17CFD /* LaunchScreen.storyboard in Resources */, 150 | C67C4DFF1BDA086200F17CFD /* Assets.xcassets in Resources */, 151 | C67C4DFD1BDA086200F17CFD /* Main.storyboard in Resources */, 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | /* End PBXResourcesBuildPhase section */ 156 | 157 | /* Begin PBXSourcesBuildPhase section */ 158 | C67C4DEB1BDA086200F17CFD /* Sources */ = { 159 | isa = PBXSourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | C67C4DFA1BDA086200F17CFD /* ViewController.m in Sources */, 163 | C67C4DF71BDA086200F17CFD /* AppDelegate.m in Sources */, 164 | C67C4E0B1BDA08FA00F17CFD /* AssetLoaderDelegate.m in Sources */, 165 | C67C4DF41BDA086200F17CFD /* main.m in Sources */, 166 | C61879561BDDF21200F4D23D /* AssetLoaderProtocol.m in Sources */, 167 | ); 168 | runOnlyForDeploymentPostprocessing = 0; 169 | }; 170 | /* End PBXSourcesBuildPhase section */ 171 | 172 | /* Begin PBXVariantGroup section */ 173 | C67C4DFB1BDA086200F17CFD /* Main.storyboard */ = { 174 | isa = PBXVariantGroup; 175 | children = ( 176 | C67C4DFC1BDA086200F17CFD /* Base */, 177 | ); 178 | name = Main.storyboard; 179 | sourceTree = ""; 180 | }; 181 | C67C4E001BDA086200F17CFD /* LaunchScreen.storyboard */ = { 182 | isa = PBXVariantGroup; 183 | children = ( 184 | C67C4E011BDA086200F17CFD /* Base */, 185 | ); 186 | name = LaunchScreen.storyboard; 187 | sourceTree = ""; 188 | }; 189 | /* End PBXVariantGroup section */ 190 | 191 | /* Begin XCBuildConfiguration section */ 192 | C67C4E041BDA086200F17CFD /* Debug */ = { 193 | isa = XCBuildConfiguration; 194 | buildSettings = { 195 | ALWAYS_SEARCH_USER_PATHS = NO; 196 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 197 | CLANG_CXX_LIBRARY = "libc++"; 198 | CLANG_ENABLE_MODULES = YES; 199 | CLANG_ENABLE_OBJC_ARC = YES; 200 | CLANG_WARN_BOOL_CONVERSION = YES; 201 | CLANG_WARN_CONSTANT_CONVERSION = YES; 202 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 203 | CLANG_WARN_EMPTY_BODY = YES; 204 | CLANG_WARN_ENUM_CONVERSION = YES; 205 | CLANG_WARN_INT_CONVERSION = YES; 206 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 207 | CLANG_WARN_UNREACHABLE_CODE = YES; 208 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 209 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 210 | COPY_PHASE_STRIP = NO; 211 | DEBUG_INFORMATION_FORMAT = dwarf; 212 | ENABLE_STRICT_OBJC_MSGSEND = YES; 213 | ENABLE_TESTABILITY = YES; 214 | GCC_C_LANGUAGE_STANDARD = gnu99; 215 | GCC_DYNAMIC_NO_PIC = NO; 216 | GCC_NO_COMMON_BLOCKS = YES; 217 | GCC_OPTIMIZATION_LEVEL = 0; 218 | GCC_PREPROCESSOR_DEFINITIONS = ( 219 | "DEBUG=1", 220 | "$(inherited)", 221 | ); 222 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 223 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 224 | GCC_WARN_UNDECLARED_SELECTOR = YES; 225 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 226 | GCC_WARN_UNUSED_FUNCTION = YES; 227 | GCC_WARN_UNUSED_VARIABLE = YES; 228 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 229 | MTL_ENABLE_DEBUG_INFO = YES; 230 | ONLY_ACTIVE_ARCH = YES; 231 | SDKROOT = iphoneos; 232 | TARGETED_DEVICE_FAMILY = "1,2"; 233 | }; 234 | name = Debug; 235 | }; 236 | C67C4E051BDA086200F17CFD /* Release */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | ALWAYS_SEARCH_USER_PATHS = NO; 240 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 241 | CLANG_CXX_LIBRARY = "libc++"; 242 | CLANG_ENABLE_MODULES = YES; 243 | CLANG_ENABLE_OBJC_ARC = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_CONSTANT_CONVERSION = YES; 246 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 247 | CLANG_WARN_EMPTY_BODY = YES; 248 | CLANG_WARN_ENUM_CONVERSION = YES; 249 | CLANG_WARN_INT_CONVERSION = YES; 250 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 251 | CLANG_WARN_UNREACHABLE_CODE = YES; 252 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 253 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 254 | COPY_PHASE_STRIP = NO; 255 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 256 | ENABLE_NS_ASSERTIONS = NO; 257 | ENABLE_STRICT_OBJC_MSGSEND = YES; 258 | GCC_C_LANGUAGE_STANDARD = gnu99; 259 | GCC_NO_COMMON_BLOCKS = YES; 260 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 261 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 262 | GCC_WARN_UNDECLARED_SELECTOR = YES; 263 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 264 | GCC_WARN_UNUSED_FUNCTION = YES; 265 | GCC_WARN_UNUSED_VARIABLE = YES; 266 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 267 | MTL_ENABLE_DEBUG_INFO = NO; 268 | SDKROOT = iphoneos; 269 | TARGETED_DEVICE_FAMILY = "1,2"; 270 | VALIDATE_PRODUCT = YES; 271 | }; 272 | name = Release; 273 | }; 274 | C67C4E071BDA086200F17CFD /* Debug */ = { 275 | isa = XCBuildConfiguration; 276 | buildSettings = { 277 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 278 | INFOPLIST_FILE = DemoAVPlayer/Info.plist; 279 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 280 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 281 | PRODUCT_BUNDLE_IDENTIFIER = com.wutian.DemoAVPlayer; 282 | PRODUCT_NAME = "$(TARGET_NAME)"; 283 | }; 284 | name = Debug; 285 | }; 286 | C67C4E081BDA086200F17CFD /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 290 | INFOPLIST_FILE = DemoAVPlayer/Info.plist; 291 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 293 | PRODUCT_BUNDLE_IDENTIFIER = com.wutian.DemoAVPlayer; 294 | PRODUCT_NAME = "$(TARGET_NAME)"; 295 | }; 296 | name = Release; 297 | }; 298 | /* End XCBuildConfiguration section */ 299 | 300 | /* Begin XCConfigurationList section */ 301 | C67C4DEA1BDA086200F17CFD /* Build configuration list for PBXProject "DemoAVPlayer" */ = { 302 | isa = XCConfigurationList; 303 | buildConfigurations = ( 304 | C67C4E041BDA086200F17CFD /* Debug */, 305 | C67C4E051BDA086200F17CFD /* Release */, 306 | ); 307 | defaultConfigurationIsVisible = 0; 308 | defaultConfigurationName = Release; 309 | }; 310 | C67C4E061BDA086200F17CFD /* Build configuration list for PBXNativeTarget "DemoAVPlayer" */ = { 311 | isa = XCConfigurationList; 312 | buildConfigurations = ( 313 | C67C4E071BDA086200F17CFD /* Debug */, 314 | C67C4E081BDA086200F17CFD /* Release */, 315 | ); 316 | defaultConfigurationIsVisible = 0; 317 | defaultConfigurationName = Release; 318 | }; 319 | /* End XCConfigurationList section */ 320 | }; 321 | rootObject = C67C4DE71BDA086200F17CFD /* Project object */; 322 | } 323 | -------------------------------------------------------------------------------- /DemoAVPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DemoAVPlayer.xcodeproj/project.xcworkspace/xcuserdata/wutian.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naituw/DemoAVAssetResourceLoaderDelegate/0517eb0af35ab0d267739d95fd2c391e965d37c9/DemoAVPlayer.xcodeproj/project.xcworkspace/xcuserdata/wutian.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /DemoAVPlayer.xcodeproj/xcuserdata/wutian.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 56 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /DemoAVPlayer.xcodeproj/xcuserdata/wutian.xcuserdatad/xcschemes/DemoAVPlayer.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 | -------------------------------------------------------------------------------- /DemoAVPlayer.xcodeproj/xcuserdata/wutian.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DemoAVPlayer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | C67C4DEE1BDA086200F17CFD 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /DemoAVPlayer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // DemoAVPlayer 4 | // 5 | // Created by 吴天 on 15/10/23. 6 | // Copyright © 2015年 Wutian. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /DemoAVPlayer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // DemoAVPlayer 4 | // 5 | // Created by 吴天 on 15/10/23. 6 | // Copyright © 2015年 Wutian. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /DemoAVPlayer/AssetLoaderDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import 4 | 5 | @interface AssetLoaderDelegate : NSObject 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /DemoAVPlayer/AssetLoaderDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | #import "AssetLoaderDelegate.h" 3 | #import 4 | #import 5 | 6 | @interface AssetLoaderDelegate () 7 | 8 | @property (nonatomic, strong) NSMutableDictionary * connectionMap; 9 | @property (nonatomic, strong) NSMutableDictionary * requestMap; 10 | 11 | @end 12 | 13 | @implementation AssetLoaderDelegate 14 | 15 | - (instancetype)init 16 | { 17 | if (self = [super init]) { 18 | self.connectionMap = [NSMutableDictionary dictionary]; 19 | self.requestMap = [NSMutableDictionary dictionary]; 20 | } 21 | return self; 22 | } 23 | 24 | - (NSURLConnection *)connectionForLoadingRequest:(AVAssetResourceLoadingRequest *)request 25 | { 26 | if (!request) { 27 | return nil; 28 | } 29 | return self.connectionMap[[NSString stringWithFormat:@"%p", request]]; 30 | } 31 | 32 | - (AVAssetResourceLoadingRequest *)loadingRequestForConnection:(NSURLConnection *)connection 33 | { 34 | if (!connection) { 35 | return nil; 36 | } 37 | for (NSString * key in _connectionMap) { 38 | NSURLConnection * value = _connectionMap[key]; 39 | if (value == connection) { 40 | return _requestMap[key]; 41 | } 42 | } 43 | return nil; 44 | } 45 | 46 | - (void)removeConnection:(NSURLConnection *)connection 47 | { 48 | AVAssetResourceLoadingRequest * request = [self loadingRequestForConnection:connection]; 49 | [self removeRequest:request]; 50 | } 51 | 52 | - (void)removeRequest:(AVAssetResourceLoadingRequest *)request 53 | { 54 | if (!request) { 55 | return; 56 | } 57 | 58 | NSString * key = [NSString stringWithFormat:@"%p", request]; 59 | 60 | NSURLConnection * c = _connectionMap[key]; 61 | [c cancel]; 62 | 63 | [_connectionMap removeObjectForKey:key]; 64 | [_requestMap removeObjectForKey:key]; 65 | } 66 | 67 | - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest 68 | { 69 | NSMutableURLRequest * request = loadingRequest.request.mutableCopy; 70 | NSURLComponents * comps = [[NSURLComponents alloc] initWithURL:request.URL resolvingAgainstBaseURL:NO]; 71 | comps.scheme = @"http"; 72 | request.URL = comps.URL; 73 | request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData; 74 | 75 | NSLog(@"request: %@", request.allHTTPHeaderFields[@"Range"]); 76 | 77 | // if (loadingRequest.dataRequest) { 78 | // long long offset = loadingRequest.dataRequest.requestedOffset; 79 | // NSInteger length = loadingRequest.dataRequest.requestedLength; 80 | // NSString *rangeValue = [NSString stringWithFormat:@"bytes=%llu-%llu", offset, offset + length - 1]; 81 | // [request setValue:rangeValue forHTTPHeaderField:@"Range"]; 82 | // } 83 | 84 | NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; 85 | 86 | _connectionMap[[NSString stringWithFormat:@"%p", loadingRequest]] = connection; 87 | _requestMap[[NSString stringWithFormat:@"%p", loadingRequest]] = loadingRequest; 88 | 89 | [connection start]; 90 | 91 | return YES; 92 | } 93 | 94 | - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest 95 | { 96 | [self removeRequest:loadingRequest]; 97 | } 98 | 99 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 100 | { 101 | NSString *contentType = [response MIMEType]; 102 | unsigned long long contentLength = [response expectedContentLength]; 103 | 104 | // 自己解析文件总大小 105 | NSString *rangeValue = [(NSHTTPURLResponse *)response allHeaderFields][@"Content-Range"]; 106 | if (rangeValue) 107 | { 108 | NSArray *rangeItems = [rangeValue componentsSeparatedByString:@"/"]; 109 | if (rangeItems.count > 1) 110 | { 111 | contentLength = [rangeItems[1] longLongValue]; 112 | } 113 | else 114 | { 115 | contentLength = [response expectedContentLength]; 116 | } 117 | } 118 | 119 | AVAssetResourceLoadingRequest * request = [self loadingRequestForConnection:connection]; 120 | request.response = response; 121 | request.contentInformationRequest.contentLength = contentLength; 122 | request.contentInformationRequest.contentType = contentType; 123 | request.contentInformationRequest.byteRangeAccessSupported = YES; 124 | } 125 | 126 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 127 | { 128 | AVAssetResourceLoadingRequest * request = [self loadingRequestForConnection:connection]; 129 | [request.dataRequest respondWithData:data]; 130 | } 131 | 132 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection 133 | { 134 | NSLog(@"request finished: %@", connection.originalRequest.allHTTPHeaderFields[@"Range"]); 135 | AVAssetResourceLoadingRequest * request = [self loadingRequestForConnection:connection]; 136 | [request finishLoading]; 137 | [self removeRequest:request]; 138 | } 139 | 140 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 141 | { 142 | NSLog(@"request failed: %@, error: %@", connection.originalRequest.allHTTPHeaderFields[@"Range"], error); 143 | 144 | AVAssetResourceLoadingRequest * request = [self loadingRequestForConnection:connection]; 145 | [request finishLoadingWithError:error]; 146 | [self removeRequest:request]; 147 | } 148 | 149 | - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response 150 | { 151 | AVAssetResourceLoadingRequest * loadingRequest = [self loadingRequestForConnection:connection]; 152 | loadingRequest.redirect = request; 153 | return request; 154 | } 155 | 156 | @end 157 | -------------------------------------------------------------------------------- /DemoAVPlayer/AssetLoaderProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // AssetLoaderProtocol.h 3 | // DemoAVPlayer 4 | // 5 | // Created by 吴天 on 15/10/26. 6 | // Copyright © 2015年 Wutian. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AssetLoaderProtocol : NSURLProtocol 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DemoAVPlayer/AssetLoaderProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // AssetLoaderProtocol.m 3 | // DemoAVPlayer 4 | // 5 | // Created by 吴天 on 15/10/26. 6 | // Copyright © 2015年 Wutian. All rights reserved. 7 | // 8 | 9 | #import "AssetLoaderProtocol.h" 10 | 11 | @interface AssetLoaderProtocol () 12 | 13 | @property (nonatomic, strong) NSURLConnection * connection; 14 | 15 | @end 16 | 17 | @implementation AssetLoaderProtocol 18 | 19 | + (BOOL)canInitWithRequest:(NSURLRequest *)request 20 | { 21 | return [request.URL.scheme isEqual:@"wbvdo"]; 22 | } 23 | 24 | + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request 25 | { 26 | return request; 27 | } 28 | 29 | - (void)startLoading 30 | { 31 | NSMutableURLRequest * request = [self.request mutableCopy]; 32 | 33 | NSURLComponents * comps = [[NSURLComponents alloc] initWithURL:request.URL resolvingAgainstBaseURL:NO]; 34 | comps.scheme = @"http"; 35 | request.URL = comps.URL; 36 | request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData; 37 | 38 | NSLog(@"request: %@", request.allHTTPHeaderFields[@"Range"]); 39 | 40 | NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; 41 | self.connection = connection; 42 | 43 | [connection start]; 44 | } 45 | 46 | - (void)stopLoading 47 | { 48 | if (self.connection) { 49 | [self.connection cancel]; 50 | self.connection = nil; 51 | } 52 | } 53 | 54 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 55 | { 56 | [self.client URLProtocol:self didFailWithError:error]; 57 | self.connection = nil; 58 | } 59 | 60 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 61 | { 62 | [self.client URLProtocol:self didLoadData:data]; 63 | } 64 | 65 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection 66 | { 67 | [self.client URLProtocolDidFinishLoading:self]; 68 | self.connection = nil; 69 | } 70 | 71 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 72 | { 73 | if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 74 | NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response; 75 | NSHTTPURLResponse * fakeResponse = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL statusCode:httpResponse.statusCode HTTPVersion:@"HTTP/1.1" headerFields:httpResponse.allHeaderFields]; 76 | response = fakeResponse; 77 | } 78 | [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; 79 | } 80 | 81 | //- (nullable NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(nullable NSURLResponse *)response 82 | //{ 83 | // NSMutableURLRequest * resultRequest = [request mutableCopy]; 84 | // NSURLComponents * comps = [[NSURLComponents alloc] initWithURL:resultRequest.URL resolvingAgainstBaseURL:NO]; 85 | // comps.scheme = @"wbvdo"; 86 | // resultRequest.URL = comps.URL; 87 | // 88 | // if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 89 | // NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response; 90 | // NSHTTPURLResponse * fakeResponse = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL statusCode:httpResponse.statusCode HTTPVersion:@"HTTP/1.1" headerFields:httpResponse.allHeaderFields]; 91 | // response = fakeResponse; 92 | // } 93 | // 94 | // [self.client URLProtocol:self wasRedirectedToRequest:resultRequest redirectResponse:response]; 95 | // return resultRequest; 96 | //} 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /DemoAVPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /DemoAVPlayer/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /DemoAVPlayer/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /DemoAVPlayer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /DemoAVPlayer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // DemoAVPlayer 4 | // 5 | // Created by 吴天 on 15/10/23. 6 | // Copyright © 2015年 Wutian. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ViewController : AVPlayerViewController 13 | 14 | + (AVPlayer *)player; 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /DemoAVPlayer/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // DemoAVPlayer 4 | // 5 | // Created by 吴天 on 15/10/23. 6 | // Copyright © 2015年 Wutian. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import "AssetLoaderDelegate.h" 12 | #import "AssetLoaderProtocol.h" 13 | 14 | @interface ViewController () 15 | 16 | @property (nonatomic, strong) AssetLoaderDelegate * loaderDelegate; 17 | 18 | @end 19 | 20 | @implementation ViewController 21 | 22 | static AVPlayer * theplayer = nil; 23 | 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | 28 | self.loaderDelegate = [[AssetLoaderDelegate alloc] init]; 29 | 30 | NSURL * url = [NSURL URLWithString:@"videotest://gslb.miaopai.com/stream/1Hjncfts3zwAecszeN4FgQ__.mp4?yx=&refer=weibo_app"]; 31 | AVURLAsset * asset = [AVURLAsset assetWithURL:url]; 32 | [asset.resourceLoader setDelegate:self.loaderDelegate queue:dispatch_get_main_queue()]; 33 | AVPlayerItem * item = [[AVPlayerItem alloc] initWithAsset:asset]; 34 | AVPlayer * player = [AVPlayer playerWithPlayerItem:item]; 35 | 36 | 37 | // [NSURLProtocol registerClass:[AssetLoaderProtocol class]]; 38 | // NSURL * url = [NSURL URLWithString:@"wbvdo://gslb.miaopai.com/stream/bMXSqHume6Tck40Ya3lsdA__.mp4?yx=&refer=weibo_app"]; 39 | // AVURLAsset * asset = [AVURLAsset assetWithURL:url]; 40 | // AVPlayerItem * item = [[AVPlayerItem alloc] initWithAsset:asset]; 41 | // AVPlayer * player = [AVPlayer playerWithPlayerItem:item]; 42 | 43 | 44 | self.player = player; 45 | 46 | theplayer = player; 47 | [player play]; 48 | } 49 | 50 | + (AVPlayer *)player 51 | { 52 | return theplayer; 53 | } 54 | 55 | - (void)didReceiveMemoryWarning { 56 | [super didReceiveMemoryWarning]; 57 | // Dispose of any resources that can be recreated. 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /DemoAVPlayer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DemoAVPlayer 4 | // 5 | // Created by 吴天 on 15/10/23. 6 | // Copyright © 2015年 Wutian. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project demostrats the "No Cancel" problem of AVAssetResourceLoaderDelegate 2 | 3 | 1. ViewController subclass AVPlayerViewController 4 | 2. ViewController loads an AVURLAsset, which resourceLoader.delegate set to AssetLoaderDelegate 5 | 3. resourceLoader:didCancelLoadingRequest: works fine on Simulator, but NOT called in real device (except first time after relaunching the iPhone, weird...). 6 | 7 | --------------------------------------------------------------------------------