├── HYNavigation.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── runlhy.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── runlhy.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── HYNavigation.xcscheme │ └── xcschememanagement.plist ├── HYNavigation ├── AppDelegate │ ├── AppDelegate.h │ └── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── more_.imageset │ │ ├── Contents.json │ │ └── more_@2x.png │ └── search_.imageset │ │ ├── Contents.json │ │ └── search_@2x.png ├── Base.lproj │ └── LaunchScreen.storyboard ├── HYPageView │ ├── HYPageView.h │ └── HYPageView.m ├── Info.plist ├── Vendors │ └── YYWebImage │ │ ├── Cache │ │ ├── YYCache.h │ │ ├── YYCache.m │ │ ├── YYDiskCache.h │ │ ├── YYDiskCache.m │ │ ├── YYKVStorage.h │ │ ├── YYKVStorage.m │ │ ├── YYMemoryCache.h │ │ └── YYMemoryCache.m │ │ ├── Categories │ │ ├── CALayer+YYWebImage.h │ │ ├── CALayer+YYWebImage.m │ │ ├── MKAnnotationView+YYWebImage.h │ │ ├── MKAnnotationView+YYWebImage.m │ │ ├── UIButton+YYWebImage.h │ │ ├── UIButton+YYWebImage.m │ │ ├── UIImage+YYWebImage.h │ │ ├── UIImage+YYWebImage.m │ │ ├── UIImageView+YYWebImage.h │ │ ├── UIImageView+YYWebImage.m │ │ ├── _YYWebImageSetter.h │ │ └── _YYWebImageSetter.m │ │ ├── Image │ │ ├── YYAnimatedImageView.h │ │ ├── YYAnimatedImageView.m │ │ ├── YYFrameImage.h │ │ ├── YYFrameImage.m │ │ ├── YYImage.h │ │ ├── YYImage.m │ │ ├── YYImageCoder.h │ │ ├── YYImageCoder.m │ │ ├── YYSpriteSheetImage.h │ │ └── YYSpriteSheetImage.m │ │ ├── YYImageCache.h │ │ ├── YYImageCache.m │ │ ├── YYWebImage.h │ │ ├── YYWebImageManager.h │ │ ├── YYWebImageManager.m │ │ ├── YYWebImageOperation.h │ │ └── YYWebImageOperation.m ├── ViewControllers │ ├── FirstViewViewController.h │ ├── FirstViewViewController.m │ ├── ViewController.h │ ├── ViewController.m │ └── WoterFlow │ │ ├── WaterFlowCollectionViewController.h │ │ ├── WaterFlowCollectionViewController.m │ │ ├── WaterFlowLayout.h │ │ └── WaterFlowLayout.m ├── Views │ ├── WaterFlowCollectionViewCell.h │ ├── WaterFlowCollectionViewCell.m │ └── WaterFlowCollectionViewCell.xib ├── main.m └── x.txt └── README.md /HYNavigation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HYNavigation.xcodeproj/project.xcworkspace/xcuserdata/runlhy.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runlhy/HYPageView/66daecc3b421ba4f03b23fce22954a905a29753e/HYNavigation.xcodeproj/project.xcworkspace/xcuserdata/runlhy.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HYNavigation.xcodeproj/xcuserdata/runlhy.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /HYNavigation.xcodeproj/xcuserdata/runlhy.xcuserdatad/xcschemes/HYNavigation.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 | -------------------------------------------------------------------------------- /HYNavigation.xcodeproj/xcuserdata/runlhy.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HYNavigation.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 62E0406C1D99910E00D6BE9D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /HYNavigation/AppDelegate/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/26. 6 | // Copyright © 2016年 Pengcent. 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 | -------------------------------------------------------------------------------- /HYNavigation/AppDelegate/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/26. 6 | // Copyright © 2016年 Pengcent. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | #import "FirstViewViewController.h" 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | 21 | 22 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 23 | 24 | ViewController *viewController = [[ViewController alloc] init]; 25 | FirstViewViewController *f = [FirstViewViewController new]; 26 | UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController]; 27 | self.window.rootViewController = viewController; 28 | 29 | self.window.backgroundColor = [UIColor whiteColor]; 30 | 31 | [self.window makeKeyAndVisible]; 32 | 33 | return YES; 34 | } 35 | 36 | - (void)applicationWillResignActive:(UIApplication *)application { 37 | // 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. 38 | // 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. 39 | } 40 | 41 | - (void)applicationDidEnterBackground:(UIApplication *)application { 42 | // 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. 43 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 44 | } 45 | 46 | - (void)applicationWillEnterForeground:(UIApplication *)application { 47 | // 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. 48 | } 49 | 50 | - (void)applicationDidBecomeActive:(UIApplication *)application { 51 | // 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. 52 | } 53 | 54 | - (void)applicationWillTerminate:(UIApplication *)application { 55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /HYNavigation/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /HYNavigation/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /HYNavigation/Assets.xcassets/more_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "more_@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HYNavigation/Assets.xcassets/more_.imageset/more_@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runlhy/HYPageView/66daecc3b421ba4f03b23fce22954a905a29753e/HYNavigation/Assets.xcassets/more_.imageset/more_@2x.png -------------------------------------------------------------------------------- /HYNavigation/Assets.xcassets/search_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "search_@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HYNavigation/Assets.xcassets/search_.imageset/search_@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runlhy/HYPageView/66daecc3b421ba4f03b23fce22954a905a29753e/HYNavigation/Assets.xcassets/search_.imageset/search_@2x.png -------------------------------------------------------------------------------- /HYNavigation/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 | 29 | -------------------------------------------------------------------------------- /HYNavigation/HYPageView/HYPageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HYPageView.h 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/27. 6 | // Copyright © 2016年 Pengcent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^ClickTitleBlock)(NSInteger); 12 | 13 | @interface HYPageView : UIScrollView 14 | typedef NS_ENUM(NSInteger, HYPageViewStyle) { 15 | HYPageViewStyleA, 16 | HYPageViewStyleB 17 | }; 18 | 19 | /** TitleButton Block */ 20 | @property (nonatomic, copy) ClickTitleBlock clickTitleBlock; 21 | 22 | // Personalized configuration properties 23 | @property (nonatomic, strong) UIFont *font; 24 | @property (nonatomic, strong) UIColor *selectedColor; 25 | @property (nonatomic, strong) UIColor *unselectedColor; 26 | @property (nonatomic, strong) UIColor *topTabBottomLineColor; 27 | @property (nonatomic, assign) CGFloat leftSpace; 28 | @property (nonatomic, assign) CGFloat rightSpace; 29 | @property (nonatomic, assign) CGFloat minSpace; 30 | @property (nonatomic, assign) NSInteger defaultSubscript; 31 | @property (nonatomic, assign) HYPageViewStyle pageViewStyle; 32 | /** 33 | default 20. 34 | For translucent status bar 35 | */ 36 | @property (nonatomic, assign) CGFloat topSpace; 37 | @property (nonatomic, strong) UIButton *leftButton; 38 | @property (nonatomic, strong) UIButton *rightButton; 39 | 40 | /** 41 | default YES. 42 | */ 43 | @property (nonatomic, assign) BOOL isAdapteNavigationBar; 44 | /** 45 | default NO. 46 | */ 47 | @property (nonatomic, assign) BOOL isAnimated; 48 | /** 49 | default YES. 50 | */ 51 | @property (nonatomic, assign) BOOL isTranslucent; 52 | /** 53 | default YES ,Valid when only one page can be filled with all buttons 54 | */ 55 | @property (nonatomic, assign) BOOL isAverage; 56 | /** 57 | default YES . 58 | */ 59 | @property (nonatomic, assign) BOOL isShowTopTabBottomLine; 60 | /** 61 | default YES . 62 | */ 63 | @property (nonatomic, assign) BOOL bodyPageBounces; 64 | /** 65 | default YES . 66 | */ 67 | @property (nonatomic, assign) BOOL bodyPageScrollEnabled; 68 | /** 69 | default NO . 70 | */ 71 | @property (nonatomic, assign) BOOL topTabBounces; 72 | 73 | 74 | 75 | /** 76 | Initializes and returns a newly allocated view object with the specified frame rectangle. 77 | 78 | @param frame ... 79 | @param titles Some title 80 | @param controllers Name of some controllers 81 | @param parameters You need to set a property called "parameter" for your controller to receive. 82 | 83 | @return self 84 | */ 85 | - (instancetype)initWithFrame:(CGRect)frame withTitles:(NSArray *)titles withViewControllers:(NSArray *)controllers withParameters:(NSArray *)parameters; 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /HYNavigation/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 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Cache/YYCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYCache.h 3 | // YYCache 4 | // 5 | // Created by ibireme on 15/2/13. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | FOUNDATION_EXPORT double YYCacheVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; 17 | #import 18 | #import 19 | #import 20 | #elif __has_include() 21 | #import 22 | #import 23 | #import 24 | #else 25 | #import "YYMemoryCache.h" 26 | #import "YYDiskCache.h" 27 | #import "YYKVStorage.h" 28 | #endif 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | 33 | /** 34 | `YYCache` is a thread safe key-value cache. 35 | 36 | It use `YYMemoryCache` to store objects in a small and fast memory cache, 37 | and use `YYDiskCache` to persisting objects to a large and slow disk cache. 38 | See `YYMemoryCache` and `YYDiskCache` for more information. 39 | */ 40 | @interface YYCache : NSObject 41 | 42 | /** The name of the cache, readonly. */ 43 | @property (copy, readonly) NSString *name; 44 | 45 | /** The underlying memory cache. see `YYMemoryCache` for more information.*/ 46 | @property (strong, readonly) YYMemoryCache *memoryCache; 47 | 48 | /** The underlying disk cache. see `YYDiskCache` for more information.*/ 49 | @property (strong, readonly) YYDiskCache *diskCache; 50 | 51 | /** 52 | Create a new instance with the specified name. 53 | Multiple instances with the same name will make the cache unstable. 54 | 55 | @param name The name of the cache. It will create a dictionary with the name in 56 | the app's caches dictionary for disk cache. Once initialized you should not 57 | read and write to this directory. 58 | @result A new cache object, or nil if an error occurs. 59 | */ 60 | - (nullable instancetype)initWithName:(NSString *)name; 61 | 62 | /** 63 | Create a new instance with the specified path. 64 | Multiple instances with the same name will make the cache unstable. 65 | 66 | @param path Full path of a directory in which the cache will write data. 67 | Once initialized you should not read and write to this directory. 68 | @result A new cache object, or nil if an error occurs. 69 | */ 70 | - (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; 71 | 72 | /** 73 | Convenience Initializers 74 | Create a new instance with the specified name. 75 | Multiple instances with the same name will make the cache unstable. 76 | 77 | @param name The name of the cache. It will create a dictionary with the name in 78 | the app's caches dictionary for disk cache. Once initialized you should not 79 | read and write to this directory. 80 | @result A new cache object, or nil if an error occurs. 81 | */ 82 | + (nullable instancetype)cacheWithName:(NSString *)name; 83 | 84 | /** 85 | Convenience Initializers 86 | Create a new instance with the specified path. 87 | Multiple instances with the same name will make the cache unstable. 88 | 89 | @param path Full path of a directory in which the cache will write data. 90 | Once initialized you should not read and write to this directory. 91 | @result A new cache object, or nil if an error occurs. 92 | */ 93 | + (nullable instancetype)cacheWithPath:(NSString *)path; 94 | 95 | - (instancetype)init UNAVAILABLE_ATTRIBUTE; 96 | + (instancetype)new UNAVAILABLE_ATTRIBUTE; 97 | 98 | #pragma mark - Access Methods 99 | ///============================================================================= 100 | /// @name Access Methods 101 | ///============================================================================= 102 | 103 | /** 104 | Returns a boolean value that indicates whether a given key is in cache. 105 | This method may blocks the calling thread until file read finished. 106 | 107 | @param key A string identifying the value. If nil, just return NO. 108 | @return Whether the key is in cache. 109 | */ 110 | - (BOOL)containsObjectForKey:(NSString *)key; 111 | 112 | /** 113 | Returns a boolean value with the block that indicates whether a given key is in cache. 114 | This method returns immediately and invoke the passed block in background queue 115 | when the operation finished. 116 | 117 | @param key A string identifying the value. If nil, just return NO. 118 | @param block A block which will be invoked in background queue when finished. 119 | */ 120 | - (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block; 121 | 122 | /** 123 | Returns the value associated with a given key. 124 | This method may blocks the calling thread until file read finished. 125 | 126 | @param key A string identifying the value. If nil, just return nil. 127 | @return The value associated with key, or nil if no value is associated with key. 128 | */ 129 | - (nullable id)objectForKey:(NSString *)key; 130 | 131 | /** 132 | Returns the value associated with a given key. 133 | This method returns immediately and invoke the passed block in background queue 134 | when the operation finished. 135 | 136 | @param key A string identifying the value. If nil, just return nil. 137 | @param block A block which will be invoked in background queue when finished. 138 | */ 139 | - (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id object))block; 140 | 141 | /** 142 | Sets the value of the specified key in the cache. 143 | This method may blocks the calling thread until file write finished. 144 | 145 | @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. 146 | @param key The key with which to associate the value. If nil, this method has no effect. 147 | */ 148 | - (void)setObject:(nullable id)object forKey:(NSString *)key; 149 | 150 | /** 151 | Sets the value of the specified key in the cache. 152 | This method returns immediately and invoke the passed block in background queue 153 | when the operation finished. 154 | 155 | @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. 156 | @param block A block which will be invoked in background queue when finished. 157 | */ 158 | - (void)setObject:(nullable id)object forKey:(NSString *)key withBlock:(nullable void(^)(void))block; 159 | 160 | /** 161 | Removes the value of the specified key in the cache. 162 | This method may blocks the calling thread until file delete finished. 163 | 164 | @param key The key identifying the value to be removed. If nil, this method has no effect. 165 | */ 166 | - (void)removeObjectForKey:(NSString *)key; 167 | 168 | /** 169 | Removes the value of the specified key in the cache. 170 | This method returns immediately and invoke the passed block in background queue 171 | when the operation finished. 172 | 173 | @param key The key identifying the value to be removed. If nil, this method has no effect. 174 | @param block A block which will be invoked in background queue when finished. 175 | */ 176 | - (void)removeObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key))block; 177 | 178 | /** 179 | Empties the cache. 180 | This method may blocks the calling thread until file delete finished. 181 | */ 182 | - (void)removeAllObjects; 183 | 184 | /** 185 | Empties the cache. 186 | This method returns immediately and invoke the passed block in background queue 187 | when the operation finished. 188 | 189 | @param block A block which will be invoked in background queue when finished. 190 | */ 191 | - (void)removeAllObjectsWithBlock:(void(^)(void))block; 192 | 193 | /** 194 | Empties the cache with block. 195 | This method returns immediately and executes the clear operation with block in background. 196 | 197 | @warning You should not send message to this instance in these blocks. 198 | @param progress This block will be invoked during removing, pass nil to ignore. 199 | @param end This block will be invoked at the end, pass nil to ignore. 200 | */ 201 | - (void)removeAllObjectsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress 202 | endBlock:(nullable void(^)(BOOL error))end; 203 | 204 | @end 205 | 206 | NS_ASSUME_NONNULL_END 207 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Cache/YYCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // YYCache.m 3 | // YYCache 4 | // 5 | // Created by ibireme on 15/2/13. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "YYCache.h" 13 | #import "YYMemoryCache.h" 14 | #import "YYDiskCache.h" 15 | 16 | @implementation YYCache 17 | 18 | - (instancetype) init { 19 | NSLog(@"Use \"initWithName\" or \"initWithPath\" to create YYCache instance."); 20 | return [self initWithPath:@""]; 21 | } 22 | 23 | - (instancetype)initWithName:(NSString *)name { 24 | if (name.length == 0) return nil; 25 | NSString *cacheFolder = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; 26 | NSString *path = [cacheFolder stringByAppendingPathComponent:name]; 27 | return [self initWithPath:path]; 28 | } 29 | 30 | - (instancetype)initWithPath:(NSString *)path { 31 | if (path.length == 0) return nil; 32 | YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path]; 33 | if (!diskCache) return nil; 34 | NSString *name = [path lastPathComponent]; 35 | YYMemoryCache *memoryCache = [YYMemoryCache new]; 36 | memoryCache.name = name; 37 | 38 | self = [super init]; 39 | _name = name; 40 | _diskCache = diskCache; 41 | _memoryCache = memoryCache; 42 | return self; 43 | } 44 | 45 | + (instancetype)cacheWithName:(NSString *)name { 46 | return [[self alloc] initWithName:name]; 47 | } 48 | 49 | + (instancetype)cacheWithPath:(NSString *)path { 50 | return [[self alloc] initWithPath:path]; 51 | } 52 | 53 | - (BOOL)containsObjectForKey:(NSString *)key { 54 | return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key]; 55 | } 56 | 57 | - (void)containsObjectForKey:(NSString *)key withBlock:(void (^)(NSString *key, BOOL contains))block { 58 | if (!block) return; 59 | 60 | if ([_memoryCache containsObjectForKey:key]) { 61 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 62 | block(key, YES); 63 | }); 64 | } else { 65 | [_diskCache containsObjectForKey:key withBlock:block]; 66 | } 67 | } 68 | 69 | - (id)objectForKey:(NSString *)key { 70 | id object = [_memoryCache objectForKey:key]; 71 | if (!object) { 72 | object = [_diskCache objectForKey:key]; 73 | if (object) { 74 | [_memoryCache setObject:object forKey:key]; 75 | } 76 | } 77 | return object; 78 | } 79 | 80 | - (void)objectForKey:(NSString *)key withBlock:(void (^)(NSString *key, id object))block { 81 | if (!block) return; 82 | id object = [_memoryCache objectForKey:key]; 83 | if (object) { 84 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 85 | block(key, object); 86 | }); 87 | } else { 88 | [_diskCache objectForKey:key withBlock:^(NSString *key, id object) { 89 | if (object && ![_memoryCache objectForKey:key]) { 90 | [_memoryCache setObject:object forKey:key]; 91 | } 92 | block(key, object); 93 | }]; 94 | } 95 | } 96 | 97 | - (void)setObject:(id)object forKey:(NSString *)key { 98 | [_memoryCache setObject:object forKey:key]; 99 | [_diskCache setObject:object forKey:key]; 100 | } 101 | 102 | - (void)setObject:(id)object forKey:(NSString *)key withBlock:(void (^)(void))block { 103 | [_memoryCache setObject:object forKey:key]; 104 | [_diskCache setObject:object forKey:key withBlock:block]; 105 | } 106 | 107 | - (void)removeObjectForKey:(NSString *)key { 108 | [_memoryCache removeObjectForKey:key]; 109 | [_diskCache removeObjectForKey:key]; 110 | } 111 | 112 | - (void)removeObjectForKey:(NSString *)key withBlock:(void (^)(NSString *key))block { 113 | [_memoryCache removeObjectForKey:key]; 114 | [_diskCache removeObjectForKey:key withBlock:block]; 115 | } 116 | 117 | - (void)removeAllObjects { 118 | [_memoryCache removeAllObjects]; 119 | [_diskCache removeAllObjects]; 120 | } 121 | 122 | - (void)removeAllObjectsWithBlock:(void(^)(void))block { 123 | [_memoryCache removeAllObjects]; 124 | [_diskCache removeAllObjectsWithBlock:block]; 125 | } 126 | 127 | - (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress 128 | endBlock:(void(^)(BOOL error))end { 129 | [_memoryCache removeAllObjects]; 130 | [_diskCache removeAllObjectsWithProgressBlock:progress endBlock:end]; 131 | 132 | } 133 | 134 | - (NSString *)description { 135 | if (_name) return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _name]; 136 | else return [NSString stringWithFormat:@"<%@: %p>", self.class, self]; 137 | } 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Cache/YYKVStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYKVStorage.h 3 | // YYCache 4 | // 5 | // Created by ibireme on 15/4/22. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | YYKVStorageItem is used by `YYKVStorage` to store key-value pair and meta data. 18 | Typically, you should not use this class directly. 19 | */ 20 | @interface YYKVStorageItem : NSObject 21 | @property (nonatomic, strong) NSString *key; ///< key 22 | @property (nonatomic, strong) NSData *value; ///< value 23 | @property (nullable, nonatomic, strong) NSString *filename; ///< filename (nil if inline) 24 | @property (nonatomic) int size; ///< value's size in bytes 25 | @property (nonatomic) int modTime; ///< modification unix timestamp 26 | @property (nonatomic) int accessTime; ///< last access unix timestamp 27 | @property (nullable, nonatomic, strong) NSData *extendedData; ///< extended data (nil if no extended data) 28 | @end 29 | 30 | /** 31 | Storage type, indicated where the `YYKVStorageItem.value` stored. 32 | 33 | @discussion Typically, write data to sqlite is faster than extern file, but 34 | reading performance is dependent on data size. In my test (on iPhone 6 64G), 35 | read data from extern file is faster than from sqlite when the data is larger 36 | than 20KB. 37 | 38 | * If you want to store large number of small datas (such as contacts cache), 39 | use YYKVStorageTypeSQLite to get better performance. 40 | * If you want to store large files (such as image cache), 41 | use YYKVStorageTypeFile to get better performance. 42 | * You can use YYKVStorageTypeMixed and choice your storage type for each item. 43 | 44 | See for more information. 45 | */ 46 | typedef NS_ENUM(NSUInteger, YYKVStorageType) { 47 | 48 | /// The `value` is stored as a file in file system. 49 | YYKVStorageTypeFile = 0, 50 | 51 | /// The `value` is stored in sqlite with blob type. 52 | YYKVStorageTypeSQLite = 1, 53 | 54 | /// The `value` is stored in file system or sqlite based on your choice. 55 | YYKVStorageTypeMixed = 2, 56 | }; 57 | 58 | 59 | 60 | /** 61 | YYKVStorage is a key-value storage based on sqlite and file system. 62 | Typically, you should not use this class directly. 63 | 64 | @discussion The designated initializer for YYKVStorage is `initWithPath:type:`. 65 | After initialized, a directory is created based on the `path` to hold key-value data. 66 | Once initialized you should not read or write this directory without the instance. 67 | 68 | You may compile the latest version of sqlite and ignore the libsqlite3.dylib in 69 | iOS system to get 2x~4x speed up. 70 | 71 | @warning The instance of this class is *NOT* thread safe, you need to make sure 72 | that there's only one thread to access the instance at the same time. If you really 73 | need to process large amounts of data in multi-thread, you should split the data 74 | to multiple KVStorage instance (sharding). 75 | */ 76 | @interface YYKVStorage : NSObject 77 | 78 | #pragma mark - Attribute 79 | ///============================================================================= 80 | /// @name Attribute 81 | ///============================================================================= 82 | 83 | @property (nonatomic, readonly) NSString *path; ///< The path of this storage. 84 | @property (nonatomic, readonly) YYKVStorageType type; ///< The type of this storage. 85 | @property (nonatomic) BOOL errorLogsEnabled; ///< Set `YES` to enable error logs for debug. 86 | 87 | #pragma mark - Initializer 88 | ///============================================================================= 89 | /// @name Initializer 90 | ///============================================================================= 91 | - (instancetype)init UNAVAILABLE_ATTRIBUTE; 92 | + (instancetype)new UNAVAILABLE_ATTRIBUTE; 93 | 94 | /** 95 | The designated initializer. 96 | 97 | @param path Full path of a directory in which the storage will write data. If 98 | the directory is not exists, it will try to create one, otherwise it will 99 | read the data in this directory. 100 | @param type The storage type. After first initialized you should not change the 101 | type of the specified path. 102 | @return A new storage object, or nil if an error occurs. 103 | @warning Multiple instances with the same path will make the storage unstable. 104 | */ 105 | - (nullable instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type NS_DESIGNATED_INITIALIZER; 106 | 107 | 108 | #pragma mark - Save Items 109 | ///============================================================================= 110 | /// @name Save Items 111 | ///============================================================================= 112 | 113 | /** 114 | Save an item or update the item with 'key' if it already exists. 115 | 116 | @discussion This method will save the item.key, item.value, item.filename and 117 | item.extendedData to disk or sqlite, other properties will be ignored. item.key 118 | and item.value should not be empty (nil or zero length). 119 | 120 | If the `type` is YYKVStorageTypeFile, then the item.filename should not be empty. 121 | If the `type` is YYKVStorageTypeSQLite, then the item.filename will be ignored. 122 | It the `type` is YYKVStorageTypeMixed, then the item.value will be saved to file 123 | system if the item.filename is not empty, otherwise it will be saved to sqlite. 124 | 125 | @param item An item. 126 | @return Whether succeed. 127 | */ 128 | - (BOOL)saveItem:(YYKVStorageItem *)item; 129 | 130 | /** 131 | Save an item or update the item with 'key' if it already exists. 132 | 133 | @discussion This method will save the key-value pair to sqlite. If the `type` is 134 | YYKVStorageTypeFile, then this method will failed. 135 | 136 | @param key The key, should not be empty (nil or zero length). 137 | @param value The key, should not be empty (nil or zero length). 138 | @return Whether succeed. 139 | */ 140 | - (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value; 141 | 142 | /** 143 | Save an item or update the item with 'key' if it already exists. 144 | 145 | @discussion 146 | If the `type` is YYKVStorageTypeFile, then the `filename` should not be empty. 147 | If the `type` is YYKVStorageTypeSQLite, then the `filename` will be ignored. 148 | It the `type` is YYKVStorageTypeMixed, then the `value` will be saved to file 149 | system if the `filename` is not empty, otherwise it will be saved to sqlite. 150 | 151 | @param key The key, should not be empty (nil or zero length). 152 | @param value The key, should not be empty (nil or zero length). 153 | @param filename The filename. 154 | @param extendedData The extended data for this item (pass nil to ignore it). 155 | 156 | @return Whether succeed. 157 | */ 158 | - (BOOL)saveItemWithKey:(NSString *)key 159 | value:(NSData *)value 160 | filename:(nullable NSString *)filename 161 | extendedData:(nullable NSData *)extendedData; 162 | 163 | #pragma mark - Remove Items 164 | ///============================================================================= 165 | /// @name Remove Items 166 | ///============================================================================= 167 | 168 | /** 169 | Remove an item with 'key'. 170 | 171 | @param key The item's key. 172 | @return Whether succeed. 173 | */ 174 | - (BOOL)removeItemForKey:(NSString *)key; 175 | 176 | /** 177 | Remove items with an array of keys. 178 | 179 | @param keys An array of specified keys. 180 | 181 | @return Whether succeed. 182 | */ 183 | - (BOOL)removeItemForKeys:(NSArray *)keys; 184 | 185 | /** 186 | Remove all items which `value` is larger than a specified size. 187 | 188 | @param size The maximum size in bytes. 189 | @return Whether succeed. 190 | */ 191 | - (BOOL)removeItemsLargerThanSize:(int)size; 192 | 193 | /** 194 | Remove all items which last access time is earlier than a specified timestamp. 195 | 196 | @param time The specified unix timestamp. 197 | @return Whether succeed. 198 | */ 199 | - (BOOL)removeItemsEarlierThanTime:(int)time; 200 | 201 | /** 202 | Remove items to make the total size not larger than a specified size. 203 | The least recently used (LRU) items will be removed first. 204 | 205 | @param maxSize The specified size in bytes. 206 | @return Whether succeed. 207 | */ 208 | - (BOOL)removeItemsToFitSize:(int)maxSize; 209 | 210 | /** 211 | Remove items to make the total count not larger than a specified count. 212 | The least recently used (LRU) items will be removed first. 213 | 214 | @param maxCount The specified item count. 215 | @return Whether succeed. 216 | */ 217 | - (BOOL)removeItemsToFitCount:(int)maxCount; 218 | 219 | /** 220 | Remove all items in background queue. 221 | 222 | @discussion This method will remove the files and sqlite database to a trash 223 | folder, and then clear the folder in background queue. So this method is much 224 | faster than `removeAllItemsWithProgressBlock:endBlock:`. 225 | 226 | @return Whether succeed. 227 | */ 228 | - (BOOL)removeAllItems; 229 | 230 | /** 231 | Remove all items. 232 | 233 | @warning You should not send message to this instance in these blocks. 234 | @param progress This block will be invoked during removing, pass nil to ignore. 235 | @param end This block will be invoked at the end, pass nil to ignore. 236 | */ 237 | - (void)removeAllItemsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress 238 | endBlock:(nullable void(^)(BOOL error))end; 239 | 240 | 241 | #pragma mark - Get Items 242 | ///============================================================================= 243 | /// @name Get Items 244 | ///============================================================================= 245 | 246 | /** 247 | Get item with a specified key. 248 | 249 | @param key A specified key. 250 | @return Item for the key, or nil if not exists / error occurs. 251 | */ 252 | - (nullable YYKVStorageItem *)getItemForKey:(NSString *)key; 253 | 254 | /** 255 | Get item information with a specified key. 256 | The `value` in this item will be ignored. 257 | 258 | @param key A specified key. 259 | @return Item information for the key, or nil if not exists / error occurs. 260 | */ 261 | - (nullable YYKVStorageItem *)getItemInfoForKey:(NSString *)key; 262 | 263 | /** 264 | Get item value with a specified key. 265 | 266 | @param key A specified key. 267 | @return Item's value, or nil if not exists / error occurs. 268 | */ 269 | - (nullable NSData *)getItemValueForKey:(NSString *)key; 270 | 271 | /** 272 | Get items with an array of keys. 273 | 274 | @param keys An array of specified keys. 275 | @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. 276 | */ 277 | - (nullable NSArray *)getItemForKeys:(NSArray *)keys; 278 | 279 | /** 280 | Get item infomartions with an array of keys. 281 | The `value` in items will be ignored. 282 | 283 | @param keys An array of specified keys. 284 | @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. 285 | */ 286 | - (nullable NSArray *)getItemInfoForKeys:(NSArray *)keys; 287 | 288 | /** 289 | Get items value with an array of keys. 290 | 291 | @param keys An array of specified keys. 292 | @return A dictionary which key is 'key' and value is 'value', or nil if not 293 | exists / error occurs. 294 | */ 295 | - (nullable NSDictionary *)getItemValueForKeys:(NSArray *)keys; 296 | 297 | #pragma mark - Get Storage Status 298 | ///============================================================================= 299 | /// @name Get Storage Status 300 | ///============================================================================= 301 | 302 | /** 303 | Whether an item exists for a specified key. 304 | 305 | @param key A specified key. 306 | 307 | @return `YES` if there's an item exists for the key, `NO` if not exists or an error occurs. 308 | */ 309 | - (BOOL)itemExistsForKey:(NSString *)key; 310 | 311 | /** 312 | Get total item count. 313 | @return Total item count, -1 when an error occurs. 314 | */ 315 | - (int)getItemsCount; 316 | 317 | /** 318 | Get item value's total size in bytes. 319 | @return Total size in bytes, -1 when an error occurs. 320 | */ 321 | - (int)getItemsSize; 322 | 323 | @end 324 | 325 | NS_ASSUME_NONNULL_END 326 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Cache/YYMemoryCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYMemoryCache.h 3 | // YYCache 4 | // 5 | // Created by ibireme on 15/2/7. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | YYMemoryCache is a fast in-memory cache that stores key-value pairs. 18 | In contrast to NSDictionary, keys are retained and not copied. 19 | The API and performance is similar to `NSCache`, all methods are thread-safe. 20 | 21 | YYMemoryCache objects differ from NSCache in a few ways: 22 | 23 | * It uses LRU (least-recently-used) to remove objects; NSCache's eviction method 24 | is non-deterministic. 25 | * It can be controlled by cost, count and age; NSCache's limits are imprecise. 26 | * It can be configured to automatically evict objects when receive memory 27 | warning or app enter background. 28 | 29 | The time of `Access Methods` in YYMemoryCache is typically in constant time (O(1)). 30 | */ 31 | @interface YYMemoryCache : NSObject 32 | 33 | #pragma mark - Attribute 34 | ///============================================================================= 35 | /// @name Attribute 36 | ///============================================================================= 37 | 38 | /** The name of the cache. Default is nil. */ 39 | @property (nullable, copy) NSString *name; 40 | 41 | /** The number of objects in the cache (read-only) */ 42 | @property (readonly) NSUInteger totalCount; 43 | 44 | /** The total cost of objects in the cache (read-only). */ 45 | @property (readonly) NSUInteger totalCost; 46 | 47 | 48 | #pragma mark - Limit 49 | ///============================================================================= 50 | /// @name Limit 51 | ///============================================================================= 52 | 53 | /** 54 | The maximum number of objects the cache should hold. 55 | 56 | @discussion The default value is NSUIntegerMax, which means no limit. 57 | This is not a strict limit—if the cache goes over the limit, some objects in the 58 | cache could be evicted later in backgound thread. 59 | */ 60 | @property NSUInteger countLimit; 61 | 62 | /** 63 | The maximum total cost that the cache can hold before it starts evicting objects. 64 | 65 | @discussion The default value is NSUIntegerMax, which means no limit. 66 | This is not a strict limit—if the cache goes over the limit, some objects in the 67 | cache could be evicted later in backgound thread. 68 | */ 69 | @property NSUInteger costLimit; 70 | 71 | /** 72 | The maximum expiry time of objects in cache. 73 | 74 | @discussion The default value is DBL_MAX, which means no limit. 75 | This is not a strict limit—if an object goes over the limit, the object could 76 | be evicted later in backgound thread. 77 | */ 78 | @property NSTimeInterval ageLimit; 79 | 80 | /** 81 | The auto trim check time interval in seconds. Default is 5.0. 82 | 83 | @discussion The cache holds an internal timer to check whether the cache reaches 84 | its limits, and if the limit is reached, it begins to evict objects. 85 | */ 86 | @property NSTimeInterval autoTrimInterval; 87 | 88 | /** 89 | If `YES`, the cache will remove all objects when the app receives a memory warning. 90 | The default value is `YES`. 91 | */ 92 | @property BOOL shouldRemoveAllObjectsOnMemoryWarning; 93 | 94 | /** 95 | If `YES`, The cache will remove all objects when the app enter background. 96 | The default value is `YES`. 97 | */ 98 | @property BOOL shouldRemoveAllObjectsWhenEnteringBackground; 99 | 100 | /** 101 | A block to be executed when the app receives a memory warning. 102 | The default value is nil. 103 | */ 104 | @property (nullable, copy) void(^didReceiveMemoryWarningBlock)(YYMemoryCache *cache); 105 | 106 | /** 107 | A block to be executed when the app enter background. 108 | The default value is nil. 109 | */ 110 | @property (nullable, copy) void(^didEnterBackgroundBlock)(YYMemoryCache *cache); 111 | 112 | /** 113 | If `YES`, the key-value pair will be released on main thread, otherwise on 114 | background thread. Default is NO. 115 | 116 | @discussion You may set this value to `YES` if the key-value object contains 117 | the instance which should be released in main thread (such as UIView/CALayer). 118 | */ 119 | @property BOOL releaseOnMainThread; 120 | 121 | /** 122 | If `YES`, the key-value pair will be released asynchronously to avoid blocking 123 | the access methods, otherwise it will be released in the access method 124 | (such as removeObjectForKey:). Default is YES. 125 | */ 126 | @property BOOL releaseAsynchronously; 127 | 128 | 129 | #pragma mark - Access Methods 130 | ///============================================================================= 131 | /// @name Access Methods 132 | ///============================================================================= 133 | 134 | /** 135 | Returns a Boolean value that indicates whether a given key is in cache. 136 | 137 | @param key An object identifying the value. If nil, just return `NO`. 138 | @return Whether the key is in cache. 139 | */ 140 | - (BOOL)containsObjectForKey:(id)key; 141 | 142 | /** 143 | Returns the value associated with a given key. 144 | 145 | @param key An object identifying the value. If nil, just return nil. 146 | @return The value associated with key, or nil if no value is associated with key. 147 | */ 148 | - (nullable id)objectForKey:(id)key; 149 | 150 | /** 151 | Sets the value of the specified key in the cache (0 cost). 152 | 153 | @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. 154 | @param key The key with which to associate the value. If nil, this method has no effect. 155 | @discussion Unlike an NSMutableDictionary object, a cache does not copy the key 156 | objects that are put into it. 157 | */ 158 | - (void)setObject:(nullable id)object forKey:(id)key; 159 | 160 | /** 161 | Sets the value of the specified key in the cache, and associates the key-value 162 | pair with the specified cost. 163 | 164 | @param object The object to store in the cache. If nil, it calls `removeObjectForKey`. 165 | @param key The key with which to associate the value. If nil, this method has no effect. 166 | @param cost The cost with which to associate the key-value pair. 167 | @discussion Unlike an NSMutableDictionary object, a cache does not copy the key 168 | objects that are put into it. 169 | */ 170 | - (void)setObject:(nullable id)object forKey:(id)key withCost:(NSUInteger)cost; 171 | 172 | /** 173 | Removes the value of the specified key in the cache. 174 | 175 | @param key The key identifying the value to be removed. If nil, this method has no effect. 176 | */ 177 | - (void)removeObjectForKey:(id)key; 178 | 179 | /** 180 | Empties the cache immediately. 181 | */ 182 | - (void)removeAllObjects; 183 | 184 | 185 | #pragma mark - Trim 186 | ///============================================================================= 187 | /// @name Trim 188 | ///============================================================================= 189 | 190 | /** 191 | Removes objects from the cache with LRU, until the `totalCount` is below or equal to 192 | the specified value. 193 | @param count The total count allowed to remain after the cache has been trimmed. 194 | */ 195 | - (void)trimToCount:(NSUInteger)count; 196 | 197 | /** 198 | Removes objects from the cache with LRU, until the `totalCost` is or equal to 199 | the specified value. 200 | @param cost The total cost allowed to remain after the cache has been trimmed. 201 | */ 202 | - (void)trimToCost:(NSUInteger)cost; 203 | 204 | /** 205 | Removes objects from the cache with LRU, until all expiry objects removed by the 206 | specified value. 207 | @param age The maximum age (in seconds) of objects. 208 | */ 209 | - (void)trimToAge:(NSTimeInterval)age; 210 | 211 | @end 212 | 213 | NS_ASSUME_NONNULL_END 214 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/CALayer+YYWebImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+YYWebImage.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/23. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | #import 14 | 15 | #if __has_include() 16 | #import 17 | #else 18 | #import "YYWebImageManager.h" 19 | #endif 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | Web image methods for CALayer. 25 | It will set image to layer.contents. 26 | */ 27 | @interface CALayer (YYWebImage) 28 | 29 | #pragma mark - image 30 | 31 | /** 32 | Current image URL. 33 | 34 | @discussion Set a new value to this property will cancel the previous request 35 | operation and create a new request operation to fetch image. Set nil to clear 36 | the image and image URL. 37 | */ 38 | @property (nullable, nonatomic, strong) NSURL *yy_imageURL; 39 | 40 | /** 41 | Set the view's `image` with a specified URL. 42 | 43 | @param imageURL The image url (remote or local file path). 44 | @param placeholder The image to be set initially, until the image request finishes. 45 | */ 46 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; 47 | 48 | /** 49 | Set the view's `image` with a specified URL. 50 | 51 | @param imageURL The image url (remote or local file path). 52 | @param options The options to use when request the image. 53 | */ 54 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; 55 | 56 | /** 57 | Set the view's `image` with a specified URL. 58 | 59 | @param imageURL The image url (remote or local file path). 60 | @param placeholder The image to be set initially, until the image request finishes. 61 | @param options The options to use when request the image. 62 | @param completion The block invoked (on main thread) when image request completed. 63 | */ 64 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 65 | placeholder:(nullable UIImage *)placeholder 66 | options:(YYWebImageOptions)options 67 | completion:(nullable YYWebImageCompletionBlock)completion; 68 | 69 | /** 70 | Set the view's `image` with a specified URL. 71 | 72 | @param imageURL The image url (remote or local file path). 73 | @param placeholder The image to be set initially, until the image request finishes. 74 | @param options The options to use when request the image. 75 | @param progress The block invoked (on main thread) during image request. 76 | @param transform The block invoked (on background thread) to do additional image process. 77 | @param completion The block invoked (on main thread) when image request completed. 78 | */ 79 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 80 | placeholder:(nullable UIImage *)placeholder 81 | options:(YYWebImageOptions)options 82 | progress:(nullable YYWebImageProgressBlock)progress 83 | transform:(nullable YYWebImageTransformBlock)transform 84 | completion:(nullable YYWebImageCompletionBlock)completion; 85 | 86 | /** 87 | Set the view's `image` with a specified URL. 88 | 89 | @param imageURL The image url (remote or local file path). 90 | @param placeholder he image to be set initially, until the image request finishes. 91 | @param options The options to use when request the image. 92 | @param manager The manager to create image request operation. 93 | @param progress The block invoked (on main thread) during image request. 94 | @param transform The block invoked (on background thread) to do additional image process. 95 | @param completion The block invoked (on main thread) when image request completed. 96 | */ 97 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 98 | placeholder:(nullable UIImage *)placeholder 99 | options:(YYWebImageOptions)options 100 | manager:(nullable YYWebImageManager *)manager 101 | progress:(nullable YYWebImageProgressBlock)progress 102 | transform:(nullable YYWebImageTransformBlock)transform 103 | completion:(nullable YYWebImageCompletionBlock)completion; 104 | 105 | /** 106 | Cancel the current image request. 107 | */ 108 | - (void)yy_cancelCurrentImageRequest; 109 | 110 | @end 111 | 112 | NS_ASSUME_NONNULL_END 113 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/CALayer+YYWebImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+YYWebImage.m 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/23. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "CALayer+YYWebImage.h" 13 | #import "YYWebImageOperation.h" 14 | #import "_YYWebImageSetter.h" 15 | #import 16 | 17 | // Dummy class for category 18 | @interface CALayer_YYWebImage : NSObject @end 19 | @implementation CALayer_YYWebImage @end 20 | 21 | 22 | static int _YYWebImageSetterKey; 23 | 24 | @implementation CALayer (YYWebImage) 25 | 26 | - (NSURL *)yy_imageURL { 27 | _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); 28 | return setter.imageURL; 29 | } 30 | 31 | - (void)setYy_imageURL:(NSURL *)imageURL { 32 | [self yy_setImageWithURL:imageURL 33 | placeholder:nil 34 | options:kNilOptions 35 | manager:nil 36 | progress:nil 37 | transform:nil 38 | completion:nil]; 39 | } 40 | 41 | - (void)yy_setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder { 42 | [self yy_setImageWithURL:imageURL 43 | placeholder:placeholder 44 | options:kNilOptions 45 | manager:nil 46 | progress:nil 47 | transform:nil 48 | completion:nil]; 49 | } 50 | 51 | - (void)yy_setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options { 52 | [self yy_setImageWithURL:imageURL 53 | placeholder:nil 54 | options:options 55 | manager:nil 56 | progress:nil 57 | transform:nil 58 | completion:nil]; 59 | } 60 | 61 | - (void)yy_setImageWithURL:(NSURL *)imageURL 62 | placeholder:(UIImage *)placeholder 63 | options:(YYWebImageOptions)options 64 | completion:(YYWebImageCompletionBlock)completion { 65 | [self yy_setImageWithURL:imageURL 66 | placeholder:placeholder 67 | options:options 68 | manager:nil 69 | progress:nil 70 | transform:nil 71 | completion:completion]; 72 | } 73 | 74 | - (void)yy_setImageWithURL:(NSURL *)imageURL 75 | placeholder:(UIImage *)placeholder 76 | options:(YYWebImageOptions)options 77 | progress:(YYWebImageProgressBlock)progress 78 | transform:(YYWebImageTransformBlock)transform 79 | completion:(YYWebImageCompletionBlock)completion { 80 | [self yy_setImageWithURL:imageURL 81 | placeholder:placeholder 82 | options:options 83 | manager:nil 84 | progress:progress 85 | transform:transform 86 | completion:completion]; 87 | } 88 | 89 | - (void)yy_setImageWithURL:(NSURL *)imageURL 90 | placeholder:(UIImage *)placeholder 91 | options:(YYWebImageOptions)options 92 | manager:(YYWebImageManager *)manager 93 | progress:(YYWebImageProgressBlock)progress 94 | transform:(YYWebImageTransformBlock)transform 95 | completion:(YYWebImageCompletionBlock)completion { 96 | if ([imageURL isKindOfClass:[NSString class]]) imageURL = [NSURL URLWithString:(id)imageURL]; 97 | manager = manager ? manager : [YYWebImageManager sharedManager]; 98 | 99 | 100 | _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); 101 | if (!setter) { 102 | setter = [_YYWebImageSetter new]; 103 | objc_setAssociatedObject(self, &_YYWebImageSetterKey, setter, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 104 | } 105 | int32_t sentinel = [setter cancelWithNewURL:imageURL]; 106 | 107 | _yy_dispatch_sync_on_main_queue(^{ 108 | if ((options & YYWebImageOptionSetImageWithFadeAnimation) && 109 | !(options & YYWebImageOptionAvoidSetImage)) { 110 | [self removeAnimationForKey:_YYWebImageFadeAnimationKey]; 111 | } 112 | 113 | if (!imageURL) { 114 | if (!(options & YYWebImageOptionIgnorePlaceHolder)) { 115 | self.contents = (id)placeholder.CGImage; 116 | } 117 | return; 118 | } 119 | 120 | // get the image from memory as quickly as possible 121 | UIImage *imageFromMemory = nil; 122 | if (manager.cache && 123 | !(options & YYWebImageOptionUseNSURLCache) && 124 | !(options & YYWebImageOptionRefreshImageCache)) { 125 | imageFromMemory = [manager.cache getImageForKey:[manager cacheKeyForURL:imageURL] withType:YYImageCacheTypeMemory]; 126 | } 127 | if (imageFromMemory) { 128 | if (!(options & YYWebImageOptionAvoidSetImage)) { 129 | self.contents = (id)imageFromMemory.CGImage; 130 | } 131 | if(completion) completion(imageFromMemory, imageURL, YYWebImageFromMemoryCacheFast, YYWebImageStageFinished, nil); 132 | return; 133 | } 134 | 135 | if (!(options & YYWebImageOptionIgnorePlaceHolder)) { 136 | self.contents = (id)placeholder.CGImage; 137 | } 138 | 139 | __weak typeof(self) _self = self; 140 | dispatch_async([_YYWebImageSetter setterQueue], ^{ 141 | YYWebImageProgressBlock _progress = nil; 142 | if (progress) _progress = ^(NSInteger receivedSize, NSInteger expectedSize) { 143 | dispatch_async(dispatch_get_main_queue(), ^{ 144 | progress(receivedSize, expectedSize); 145 | }); 146 | }; 147 | 148 | __block int32_t newSentinel = 0; 149 | __block __weak typeof(setter) weakSetter = nil; 150 | YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { 151 | __strong typeof(_self) self = _self; 152 | BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); 153 | BOOL showFade = (options & YYWebImageOptionSetImageWithFadeAnimation); 154 | dispatch_async(dispatch_get_main_queue(), ^{ 155 | BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; 156 | if (setImage && self && !sentinelChanged) { 157 | if (showFade) { 158 | CATransition *transition = [CATransition animation]; 159 | transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime; 160 | transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 161 | transition.type = kCATransitionFade; 162 | [self addAnimation:transition forKey:_YYWebImageFadeAnimationKey]; 163 | } 164 | self.contents = (id)image.CGImage; 165 | } 166 | if (completion) { 167 | if (sentinelChanged) { 168 | completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); 169 | } else { 170 | completion(image, url, from, stage, error); 171 | } 172 | } 173 | }); 174 | }; 175 | 176 | newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; 177 | weakSetter = setter; 178 | }); 179 | 180 | 181 | }); 182 | } 183 | 184 | - (void)yy_cancelCurrentImageRequest { 185 | _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); 186 | if (setter) [setter cancel]; 187 | } 188 | 189 | @end 190 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/MKAnnotationView+YYWebImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MKAnnotationView+YYWebImage.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/23. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | #import 14 | 15 | #if __has_include() 16 | #import 17 | #else 18 | #import "YYWebImageManager.h" 19 | #endif 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | Web image methods for MKAnnotationView. 25 | */ 26 | @interface MKAnnotationView (YYWebImage) 27 | 28 | /** 29 | Current image URL. 30 | 31 | @discussion Set a new value to this property will cancel the previous request 32 | operation and create a new request operation to fetch image. Set nil to clear 33 | the image and image URL. 34 | */ 35 | @property (nullable, nonatomic, strong) NSURL *yy_imageURL; 36 | 37 | /** 38 | Set the view's `image` with a specified URL. 39 | 40 | @param imageURL The image url (remote or local file path). 41 | @param placeholder The image to be set initially, until the image request finishes. 42 | */ 43 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; 44 | 45 | /** 46 | Set the view's `image` with a specified URL. 47 | 48 | @param imageURL The image url (remote or local file path). 49 | @param options The options to use when request the image. 50 | */ 51 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; 52 | 53 | /** 54 | Set the view's `image` with a specified URL. 55 | 56 | @param imageURL The image url (remote or local file path). 57 | @param placeholder The image to be set initially, until the image request finishes. 58 | @param options The options to use when request the image. 59 | @param completion The block invoked (on main thread) when image request completed. 60 | */ 61 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 62 | placeholder:(nullable UIImage *)placeholder 63 | options:(YYWebImageOptions)options 64 | completion:(nullable YYWebImageCompletionBlock)completion; 65 | 66 | /** 67 | Set the view's `image` with a specified URL. 68 | 69 | @param imageURL The image url (remote or local file path). 70 | @param placeholder The image to be set initially, until the image request finishes. 71 | @param options The options to use when request the image. 72 | @param progress The block invoked (on main thread) during image request. 73 | @param transform The block invoked (on background thread) to do additional image process. 74 | @param completion The block invoked (on main thread) when image request completed. 75 | */ 76 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 77 | placeholder:(nullable UIImage *)placeholder 78 | options:(YYWebImageOptions)options 79 | progress:(nullable YYWebImageProgressBlock)progress 80 | transform:(nullable YYWebImageTransformBlock)transform 81 | completion:(nullable YYWebImageCompletionBlock)completion; 82 | 83 | /** 84 | Set the view's `image` with a specified URL. 85 | 86 | @param imageURL The image url (remote or local file path). 87 | @param placeholder he image to be set initially, until the image request finishes. 88 | @param options The options to use when request the image. 89 | @param manager The manager to create image request operation. 90 | @param progress The block invoked (on main thread) during image request. 91 | @param transform The block invoked (on background thread) to do additional image process. 92 | @param completion The block invoked (on main thread) when image request completed. 93 | */ 94 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 95 | placeholder:(nullable UIImage *)placeholder 96 | options:(YYWebImageOptions)options 97 | manager:(nullable YYWebImageManager *)manager 98 | progress:(nullable YYWebImageProgressBlock)progress 99 | transform:(nullable YYWebImageTransformBlock)transform 100 | completion:(nullable YYWebImageCompletionBlock)completion; 101 | 102 | /** 103 | Cancel the current image request. 104 | */ 105 | - (void)yy_cancelCurrentImageRequest; 106 | 107 | @end 108 | 109 | NS_ASSUME_NONNULL_END 110 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/MKAnnotationView+YYWebImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKAnnotationView+YYWebImage.m 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/23. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "MKAnnotationView+YYWebImage.h" 13 | #import "YYWebImageOperation.h" 14 | #import "_YYWebImageSetter.h" 15 | #import 16 | 17 | // Dummy class for category 18 | @interface MKAnnotationView_YYWebImage : NSObject @end 19 | @implementation MKAnnotationView_YYWebImage @end 20 | 21 | 22 | static int _YYWebImageSetterKey; 23 | 24 | @implementation MKAnnotationView (YYWebImage) 25 | 26 | - (NSURL *)yy_imageURL { 27 | _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); 28 | return setter.imageURL; 29 | } 30 | 31 | - (void)setYy_imageURL:(NSURL *)imageURL { 32 | [self yy_setImageWithURL:imageURL 33 | placeholder:nil 34 | options:kNilOptions 35 | manager:nil 36 | progress:nil 37 | transform:nil 38 | completion:nil]; 39 | } 40 | 41 | - (void)yy_setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder { 42 | [self yy_setImageWithURL:imageURL 43 | placeholder:placeholder 44 | options:kNilOptions 45 | manager:nil 46 | progress:nil 47 | transform:nil 48 | completion:nil]; 49 | } 50 | 51 | - (void)yy_setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options { 52 | [self yy_setImageWithURL:imageURL 53 | placeholder:nil 54 | options:options 55 | manager:nil 56 | progress:nil 57 | transform:nil 58 | completion:nil]; 59 | } 60 | 61 | - (void)yy_setImageWithURL:(NSURL *)imageURL 62 | placeholder:(UIImage *)placeholder 63 | options:(YYWebImageOptions)options 64 | completion:(YYWebImageCompletionBlock)completion { 65 | [self yy_setImageWithURL:imageURL 66 | placeholder:placeholder 67 | options:options 68 | manager:nil 69 | progress:nil 70 | transform:nil 71 | completion:completion]; 72 | } 73 | 74 | - (void)yy_setImageWithURL:(NSURL *)imageURL 75 | placeholder:(UIImage *)placeholder 76 | options:(YYWebImageOptions)options 77 | progress:(YYWebImageProgressBlock)progress 78 | transform:(YYWebImageTransformBlock)transform 79 | completion:(YYWebImageCompletionBlock)completion { 80 | [self yy_setImageWithURL:imageURL 81 | placeholder:placeholder 82 | options:options 83 | manager:nil 84 | progress:progress 85 | transform:transform 86 | completion:completion]; 87 | } 88 | 89 | - (void)yy_setImageWithURL:(NSURL *)imageURL 90 | placeholder:(UIImage *)placeholder 91 | options:(YYWebImageOptions)options 92 | manager:(YYWebImageManager *)manager 93 | progress:(YYWebImageProgressBlock)progress 94 | transform:(YYWebImageTransformBlock)transform 95 | completion:(YYWebImageCompletionBlock)completion { 96 | if ([imageURL isKindOfClass:[NSString class]]) imageURL = [NSURL URLWithString:(id)imageURL]; 97 | manager = manager ? manager : [YYWebImageManager sharedManager]; 98 | 99 | _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); 100 | if (!setter) { 101 | setter = [_YYWebImageSetter new]; 102 | objc_setAssociatedObject(self, &_YYWebImageSetterKey, setter, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 103 | } 104 | int32_t sentinel = [setter cancelWithNewURL:imageURL]; 105 | 106 | _yy_dispatch_sync_on_main_queue(^{ 107 | if ((options & YYWebImageOptionSetImageWithFadeAnimation) && 108 | !(options & YYWebImageOptionAvoidSetImage)) { 109 | if (!self.highlighted) { 110 | [self.layer removeAnimationForKey:_YYWebImageFadeAnimationKey]; 111 | } 112 | } 113 | if (!imageURL) { 114 | if (!(options & YYWebImageOptionIgnorePlaceHolder)) { 115 | self.image = placeholder; 116 | } 117 | return; 118 | } 119 | 120 | // get the image from memory as quickly as possible 121 | UIImage *imageFromMemory = nil; 122 | if (manager.cache && 123 | !(options & YYWebImageOptionUseNSURLCache) && 124 | !(options & YYWebImageOptionRefreshImageCache)) { 125 | imageFromMemory = [manager.cache getImageForKey:[manager cacheKeyForURL:imageURL] withType:YYImageCacheTypeMemory]; 126 | } 127 | if (imageFromMemory) { 128 | if (!(options & YYWebImageOptionAvoidSetImage)) { 129 | self.image = imageFromMemory; 130 | } 131 | if(completion) completion(imageFromMemory, imageURL, YYWebImageFromMemoryCacheFast, YYWebImageStageFinished, nil); 132 | return; 133 | } 134 | 135 | if (!(options & YYWebImageOptionIgnorePlaceHolder)) { 136 | self.image = placeholder; 137 | } 138 | 139 | __weak typeof(self) _self = self; 140 | dispatch_async([_YYWebImageSetter setterQueue], ^{ 141 | YYWebImageProgressBlock _progress = nil; 142 | if (progress) _progress = ^(NSInteger receivedSize, NSInteger expectedSize) { 143 | dispatch_async(dispatch_get_main_queue(), ^{ 144 | progress(receivedSize, expectedSize); 145 | }); 146 | }; 147 | 148 | __block int32_t newSentinel = 0; 149 | __block __weak typeof(setter) weakSetter = nil; 150 | YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { 151 | __strong typeof(_self) self = _self; 152 | BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); 153 | BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && !self.highlighted); 154 | dispatch_async(dispatch_get_main_queue(), ^{ 155 | BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; 156 | if (setImage && self && !sentinelChanged) { 157 | if (showFade) { 158 | CATransition *transition = [CATransition animation]; 159 | transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime; 160 | transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 161 | transition.type = kCATransitionFade; 162 | [self.layer addAnimation:transition forKey:_YYWebImageFadeAnimationKey]; 163 | } 164 | self.image = image; 165 | } 166 | if (completion) { 167 | if (sentinelChanged) { 168 | completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); 169 | } else { 170 | completion(image, url, from, stage, error); 171 | } 172 | } 173 | }); 174 | }; 175 | 176 | newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; 177 | weakSetter = setter; 178 | }); 179 | }); 180 | } 181 | 182 | - (void)yy_cancelCurrentImageRequest { 183 | _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); 184 | if (setter) [setter cancel]; 185 | } 186 | 187 | @end 188 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/UIButton+YYWebImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+YYWebImage.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/23. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | #import 16 | #else 17 | #import "YYWebImageManager.h" 18 | #endif 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | Web image methods for UIButton. 24 | */ 25 | @interface UIButton (YYWebImage) 26 | 27 | #pragma mark - image 28 | 29 | /** 30 | Current image URL for the specified state. 31 | @return The image URL, or nil. 32 | */ 33 | - (nullable NSURL *)yy_imageURLForState:(UIControlState)state; 34 | 35 | /** 36 | Set the button's image with a specified URL for the specified state. 37 | 38 | @param imageURL The image url (remote or local file path). 39 | @param state The state that uses the specified image. 40 | @param placeholder The image to be set initially, until the image request finishes. 41 | */ 42 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 43 | forState:(UIControlState)state 44 | placeholder:(nullable UIImage *)placeholder; 45 | 46 | /** 47 | Set the button's image with a specified URL for the specified state. 48 | 49 | @param imageURL The image url (remote or local file path). 50 | @param state The state that uses the specified image. 51 | @param options The options to use when request the image. 52 | */ 53 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 54 | forState:(UIControlState)state 55 | options:(YYWebImageOptions)options; 56 | 57 | /** 58 | Set the button's image with a specified URL for the specified state. 59 | 60 | @param imageURL The image url (remote or local file path). 61 | @param state The state that uses the specified image. 62 | @param placeholder The image to be set initially, until the image request finishes. 63 | @param options The options to use when request the image. 64 | @param completion The block invoked (on main thread) when image request completed. 65 | */ 66 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 67 | forState:(UIControlState)state 68 | placeholder:(nullable UIImage *)placeholder 69 | options:(YYWebImageOptions)options 70 | completion:(nullable YYWebImageCompletionBlock)completion; 71 | 72 | /** 73 | Set the button's image with a specified URL for the specified state. 74 | 75 | @param imageURL The image url (remote or local file path). 76 | @param state The state that uses the specified image. 77 | @param placeholder The image to be set initially, until the image request finishes. 78 | @param options The options to use when request the image. 79 | @param progress The block invoked (on main thread) during image request. 80 | @param transform The block invoked (on background thread) to do additional image process. 81 | @param completion The block invoked (on main thread) when image request completed. 82 | */ 83 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 84 | forState:(UIControlState)state 85 | placeholder:(nullable UIImage *)placeholder 86 | options:(YYWebImageOptions)options 87 | progress:(nullable YYWebImageProgressBlock)progress 88 | transform:(nullable YYWebImageTransformBlock)transform 89 | completion:(nullable YYWebImageCompletionBlock)completion; 90 | 91 | /** 92 | Set the button's image with a specified URL for the specified state. 93 | 94 | @param imageURL The image url (remote or local file path). 95 | @param state The state that uses the specified image. 96 | @param placeholder The image to be set initially, until the image request finishes. 97 | @param options The options to use when request the image. 98 | @param manager The manager to create image request operation. 99 | @param progress The block invoked (on main thread) during image request. 100 | @param transform The block invoked (on background thread) to do additional image process. 101 | @param completion The block invoked (on main thread) when image request completed. 102 | */ 103 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 104 | forState:(UIControlState)state 105 | placeholder:(nullable UIImage *)placeholder 106 | options:(YYWebImageOptions)options 107 | manager:(nullable YYWebImageManager *)manager 108 | progress:(nullable YYWebImageProgressBlock)progress 109 | transform:(nullable YYWebImageTransformBlock)transform 110 | completion:(nullable YYWebImageCompletionBlock)completion; 111 | 112 | /** 113 | Cancel the current image request for a specified state. 114 | @param state The state that uses the specified image. 115 | */ 116 | - (void)yy_cancelImageRequestForState:(UIControlState)state; 117 | 118 | 119 | 120 | #pragma mark - background image 121 | 122 | /** 123 | Current backgroundImage URL for the specified state. 124 | @return The image URL, or nil. 125 | */ 126 | - (nullable NSURL *)yy_backgroundImageURLForState:(UIControlState)state; 127 | 128 | /** 129 | Set the button's backgroundImage with a specified URL for the specified state. 130 | 131 | @param imageURL The image url (remote or local file path). 132 | @param state The state that uses the specified image. 133 | @param placeholder The image to be set initially, until the image request finishes. 134 | */ 135 | - (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL 136 | forState:(UIControlState)state 137 | placeholder:(nullable UIImage *)placeholder; 138 | 139 | /** 140 | Set the button's backgroundImage with a specified URL for the specified state. 141 | 142 | @param imageURL The image url (remote or local file path). 143 | @param state The state that uses the specified image. 144 | @param options The options to use when request the image. 145 | */ 146 | - (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL 147 | forState:(UIControlState)state 148 | options:(YYWebImageOptions)options; 149 | 150 | /** 151 | Set the button's backgroundImage with a specified URL for the specified state. 152 | 153 | @param imageURL The image url (remote or local file path). 154 | @param state The state that uses the specified image. 155 | @param placeholder The image to be set initially, until the image request finishes. 156 | @param options The options to use when request the image. 157 | @param completion The block invoked (on main thread) when image request completed. 158 | */ 159 | - (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL 160 | forState:(UIControlState)state 161 | placeholder:(nullable UIImage *)placeholder 162 | options:(YYWebImageOptions)options 163 | completion:(nullable YYWebImageCompletionBlock)completion; 164 | 165 | /** 166 | Set the button's backgroundImage with a specified URL for the specified state. 167 | 168 | @param imageURL The image url (remote or local file path). 169 | @param state The state that uses the specified image. 170 | @param placeholder The image to be set initially, until the image request finishes. 171 | @param options The options to use when request the image. 172 | @param progress The block invoked (on main thread) during image request. 173 | @param transform The block invoked (on background thread) to do additional image process. 174 | @param completion The block invoked (on main thread) when image request completed. 175 | */ 176 | - (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL 177 | forState:(UIControlState)state 178 | placeholder:(nullable UIImage *)placeholder 179 | options:(YYWebImageOptions)options 180 | progress:(nullable YYWebImageProgressBlock)progress 181 | transform:(nullable YYWebImageTransformBlock)transform 182 | completion:(nullable YYWebImageCompletionBlock)completion; 183 | 184 | /** 185 | Set the button's backgroundImage with a specified URL for the specified state. 186 | 187 | @param imageURL The image url (remote or local file path). 188 | @param state The state that uses the specified image. 189 | @param placeholder The image to be set initially, until the image request finishes. 190 | @param options The options to use when request the image. 191 | @param manager The manager to create image request operation. 192 | @param progress The block invoked (on main thread) during image request. 193 | @param transform The block invoked (on background thread) to do additional image process. 194 | @param completion The block invoked (on main thread) when image request completed. 195 | */ 196 | - (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL 197 | forState:(UIControlState)state 198 | placeholder:(nullable UIImage *)placeholder 199 | options:(YYWebImageOptions)options 200 | manager:(nullable YYWebImageManager *)manager 201 | progress:(nullable YYWebImageProgressBlock)progress 202 | transform:(nullable YYWebImageTransformBlock)transform 203 | completion:(nullable YYWebImageCompletionBlock)completion; 204 | 205 | /** 206 | Cancel the current backgroundImage request for a specified state. 207 | @param state The state that uses the specified image. 208 | */ 209 | - (void)yy_cancelBackgroundImageRequestForState:(UIControlState)state; 210 | 211 | @end 212 | 213 | NS_ASSUME_NONNULL_END 214 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/UIImage+YYWebImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+YYWebImage.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 13/4/4. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | Provide some commen method for `UIImage`. 18 | Image process is based on CoreGraphic and vImage. 19 | */ 20 | @interface UIImage (YYWebImage) 21 | 22 | #pragma mark - Create image 23 | ///============================================================================= 24 | /// @name Create image 25 | ///============================================================================= 26 | 27 | /** 28 | Create an animated image with GIF data. After created, you can access 29 | the images via property '.images'. If the data is not animated gif, this 30 | function is same as [UIImage imageWithData:data scale:scale]; 31 | 32 | @discussion It has a better display performance, but costs more memory 33 | (width * height * frames Bytes). It only suited to display small 34 | gif such as animated emoticon. If you want to display large gif, 35 | see `YYImage`. 36 | 37 | @param data GIF data. 38 | 39 | @param scale The scale factor 40 | 41 | @return A new image created from GIF, or nil when an error occurs. 42 | */ 43 | + (nullable UIImage *)yy_imageWithSmallGIFData:(NSData *)data scale:(CGFloat)scale; 44 | 45 | /** 46 | Create and return a 1x1 point size image with the given color. 47 | 48 | @param color The color. 49 | */ 50 | + (nullable UIImage *)yy_imageWithColor:(UIColor *)color; 51 | 52 | /** 53 | Create and return a pure color image with the given color and size. 54 | 55 | @param color The color. 56 | @param size New image's type. 57 | */ 58 | + (nullable UIImage *)yy_imageWithColor:(UIColor *)color size:(CGSize)size; 59 | 60 | /** 61 | Create and return an image with custom draw code. 62 | 63 | @param size The image size. 64 | @param drawBlock The draw block. 65 | 66 | @return The new image. 67 | */ 68 | + (nullable UIImage *)yy_imageWithSize:(CGSize)size drawBlock:(void (^)(CGContextRef context))drawBlock; 69 | 70 | #pragma mark - Image Info 71 | ///============================================================================= 72 | /// @name Image Info 73 | ///============================================================================= 74 | 75 | /** 76 | Whether this image has alpha channel. 77 | */ 78 | - (BOOL)yy_hasAlphaChannel; 79 | 80 | 81 | #pragma mark - Modify Image 82 | ///============================================================================= 83 | /// @name Modify Image 84 | ///============================================================================= 85 | 86 | /** 87 | Draws the entire image in the specified rectangle, content changed with 88 | the contentMode. 89 | 90 | @discussion This method draws the entire image in the current graphics context, 91 | respecting the image's orientation setting. In the default coordinate system, 92 | images are situated down and to the right of the origin of the specified 93 | rectangle. This method respects any transforms applied to the current graphics 94 | context, however. 95 | 96 | @param rect The rectangle in which to draw the image. 97 | 98 | @param contentMode Draw content mode 99 | 100 | @param clips A Boolean value that determines whether content are confined to the rect. 101 | */ 102 | - (void)yy_drawInRect:(CGRect)rect withContentMode:(UIViewContentMode)contentMode clipsToBounds:(BOOL)clips; 103 | 104 | /** 105 | Returns a new image which is scaled from this image. 106 | The image will be stretched as needed. 107 | 108 | @param size The new size to be scaled, values should be positive. 109 | 110 | @return The new image with the given size. 111 | */ 112 | - (nullable UIImage *)yy_imageByResizeToSize:(CGSize)size; 113 | 114 | /** 115 | Returns a new image which is scaled from this image. 116 | The image content will be changed with thencontentMode. 117 | 118 | @param size The new size to be scaled, values should be positive. 119 | 120 | @param contentMode The content mode for image content. 121 | 122 | @return The new image with the given size. 123 | */ 124 | - (nullable UIImage *)yy_imageByResizeToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode; 125 | 126 | /** 127 | Returns a new image which is cropped from this image. 128 | 129 | @param rect Image's inner rect. 130 | 131 | @return The new image, or nil if an error occurs. 132 | */ 133 | - (nullable UIImage *)yy_imageByCropToRect:(CGRect)rect; 134 | 135 | /** 136 | Returns a new image which is edge inset from this image. 137 | 138 | @param insets Inset (positive) for each of the edges, values can be negative to 'outset'. 139 | 140 | @param color Extend edge's fill color, nil means clear color. 141 | 142 | @return The new image, or nil if an error occurs. 143 | */ 144 | - (nullable UIImage *)yy_imageByInsetEdge:(UIEdgeInsets)insets withColor:(nullable UIColor *)color; 145 | 146 | /** 147 | Rounds a new image with a given corner size. 148 | 149 | @param radius The radius of each corner oval. Values larger than half the 150 | rectangle's width or height are clamped appropriately to half 151 | the width or height. 152 | */ 153 | - (nullable UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius; 154 | 155 | /** 156 | Rounds a new image with a given corner size. 157 | 158 | @param radius The radius of each corner oval. Values larger than half the 159 | rectangle's width or height are clamped appropriately to 160 | half the width or height. 161 | 162 | @param borderWidth The inset border line width. Values larger than half the rectangle's 163 | width or height are clamped appropriately to half the width 164 | or height. 165 | 166 | @param borderColor The border stroke color. nil means clear color. 167 | */ 168 | - (nullable UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius 169 | borderWidth:(CGFloat)borderWidth 170 | borderColor:(nullable UIColor *)borderColor; 171 | 172 | /** 173 | Rounds a new image with a given corner size. 174 | 175 | @param radius The radius of each corner oval. Values larger than half the 176 | rectangle's width or height are clamped appropriately to 177 | half the width or height. 178 | 179 | @param corners A bitmask value that identifies the corners that you want 180 | rounded. You can use this parameter to round only a subset 181 | of the corners of the rectangle. 182 | 183 | @param borderWidth The inset border line width. Values larger than half the rectangle's 184 | width or height are clamped appropriately to half the width 185 | or height. 186 | 187 | @param borderColor The border stroke color. nil means clear color. 188 | 189 | @param borderLineJoin The border line join. 190 | */ 191 | - (nullable UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius 192 | corners:(UIRectCorner)corners 193 | borderWidth:(CGFloat)borderWidth 194 | borderColor:(nullable UIColor *)borderColor 195 | borderLineJoin:(CGLineJoin)borderLineJoin; 196 | 197 | /** 198 | Returns a new rotated image (relative to the center). 199 | 200 | @param radians Rotated radians in counterclockwise.⟲ 201 | 202 | @param fitSize YES: new image's size is extend to fit all content. 203 | NO: image's size will not change, content may be clipped. 204 | */ 205 | - (nullable UIImage *)yy_imageByRotate:(CGFloat)radians fitSize:(BOOL)fitSize; 206 | 207 | /** 208 | Returns a new image rotated counterclockwise by a quarter‑turn (90°). ⤺ 209 | The width and height will be exchanged. 210 | */ 211 | - (nullable UIImage *)yy_imageByRotateLeft90; 212 | 213 | /** 214 | Returns a new image rotated clockwise by a quarter‑turn (90°). ⤼ 215 | The width and height will be exchanged. 216 | */ 217 | - (nullable UIImage *)yy_imageByRotateRight90; 218 | 219 | /** 220 | Returns a new image rotated 180° . ↻ 221 | */ 222 | - (nullable UIImage *)yy_imageByRotate180; 223 | 224 | /** 225 | Returns a vertically flipped image. ⥯ 226 | */ 227 | - (nullable UIImage *)yy_imageByFlipVertical; 228 | 229 | /** 230 | Returns a horizontally flipped image. ⇋ 231 | */ 232 | - (nullable UIImage *)yy_imageByFlipHorizontal; 233 | 234 | 235 | #pragma mark - Image Effect 236 | ///============================================================================= 237 | /// @name Image Effect 238 | ///============================================================================= 239 | 240 | /** 241 | Tint the image in alpha channel with the given color. 242 | 243 | @param color The color. 244 | */ 245 | - (nullable UIImage *)yy_imageByTintColor:(UIColor *)color; 246 | 247 | /** 248 | Returns a grayscaled image. 249 | */ 250 | - (nullable UIImage *)yy_imageByGrayscale; 251 | 252 | /** 253 | Applies a blur effect to this image. Suitable for blur any content. 254 | */ 255 | - (nullable UIImage *)yy_imageByBlurSoft; 256 | 257 | /** 258 | Applies a blur effect to this image. Suitable for blur any content except pure white. 259 | (same as iOS Control Panel) 260 | */ 261 | - (nullable UIImage *)yy_imageByBlurLight; 262 | 263 | /** 264 | Applies a blur effect to this image. Suitable for displaying black text. 265 | (same as iOS Navigation Bar White) 266 | */ 267 | - (nullable UIImage *)yy_imageByBlurExtraLight; 268 | 269 | /** 270 | Applies a blur effect to this image. Suitable for displaying white text. 271 | (same as iOS Notification Center) 272 | */ 273 | - (nullable UIImage *)yy_imageByBlurDark; 274 | 275 | /** 276 | Applies a blur and tint color to this image. 277 | 278 | @param tintColor The tint color. 279 | */ 280 | - (nullable UIImage *)yy_imageByBlurWithTint:(UIColor *)tintColor; 281 | 282 | /** 283 | Applies a blur, tint color, and saturation adjustment to this image, 284 | optionally within the area specified by @a maskImage. 285 | 286 | @param blurRadius The radius of the blur in points, 0 means no blur effect. 287 | 288 | @param tintColor An optional UIColor object that is uniformly blended with 289 | the result of the blur and saturation operations. The 290 | alpha channel of this color determines how strong the 291 | tint is. nil means no tint. 292 | 293 | @param tintBlendMode The @a tintColor blend mode. Default is kCGBlendModeNormal (0). 294 | 295 | @param saturation A value of 1.0 produces no change in the resulting image. 296 | Values less than 1.0 will desaturation the resulting image 297 | while values greater than 1.0 will have the opposite effect. 298 | 0 means gray scale. 299 | 300 | @param maskImage If specified, @a inputImage is only modified in the area(s) 301 | defined by this mask. This must be an image mask or it 302 | must meet the requirements of the mask parameter of 303 | CGContextClipToMask. 304 | 305 | @return image with effect, or nil if an error occurs (e.g. no 306 | enough memory). 307 | */ 308 | - (nullable UIImage *)yy_imageByBlurRadius:(CGFloat)blurRadius 309 | tintColor:(nullable UIColor *)tintColor 310 | tintMode:(CGBlendMode)tintBlendMode 311 | saturation:(CGFloat)saturation 312 | maskImage:(nullable UIImage *)maskImage; 313 | 314 | @end 315 | 316 | NS_ASSUME_NONNULL_END 317 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/UIImageView+YYWebImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+YYWebImage.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/23. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | #import 16 | #else 17 | #import "YYWebImageManager.h" 18 | #endif 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | Web image methods for UIImageView. 24 | */ 25 | @interface UIImageView (YYWebImage) 26 | 27 | #pragma mark - image 28 | 29 | /** 30 | Current image URL. 31 | 32 | @discussion Set a new value to this property will cancel the previous request 33 | operation and create a new request operation to fetch image. Set nil to clear 34 | the image and image URL. 35 | */ 36 | @property (nullable, nonatomic, strong) NSURL *yy_imageURL; 37 | 38 | /** 39 | Set the view's `image` with a specified URL. 40 | 41 | @param imageURL The image url (remote or local file path). 42 | @param placeholder The image to be set initially, until the image request finishes. 43 | */ 44 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; 45 | 46 | /** 47 | Set the view's `image` with a specified URL. 48 | 49 | @param imageURL The image url (remote or local file path). 50 | @param options The options to use when request the image. 51 | */ 52 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; 53 | 54 | /** 55 | Set the view's `image` with a specified URL. 56 | 57 | @param imageURL The image url (remote or local file path). 58 | @param placeholder The image to be set initially, until the image request finishes. 59 | @param options The options to use when request the image. 60 | @param completion The block invoked (on main thread) when image request completed. 61 | */ 62 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 63 | placeholder:(nullable UIImage *)placeholder 64 | options:(YYWebImageOptions)options 65 | completion:(nullable YYWebImageCompletionBlock)completion; 66 | 67 | /** 68 | Set the view's `image` with a specified URL. 69 | 70 | @param imageURL The image url (remote or local file path). 71 | @param placeholder The image to be set initially, until the image request finishes. 72 | @param options The options to use when request the image. 73 | @param progress The block invoked (on main thread) during image request. 74 | @param transform The block invoked (on background thread) to do additional image process. 75 | @param completion The block invoked (on main thread) when image request completed. 76 | */ 77 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 78 | placeholder:(nullable UIImage *)placeholder 79 | options:(YYWebImageOptions)options 80 | progress:(nullable YYWebImageProgressBlock)progress 81 | transform:(nullable YYWebImageTransformBlock)transform 82 | completion:(nullable YYWebImageCompletionBlock)completion; 83 | 84 | /** 85 | Set the view's `image` with a specified URL. 86 | 87 | @param imageURL The image url (remote or local file path). 88 | @param placeholder he image to be set initially, until the image request finishes. 89 | @param options The options to use when request the image. 90 | @param manager The manager to create image request operation. 91 | @param progress The block invoked (on main thread) during image request. 92 | @param transform The block invoked (on background thread) to do additional image process. 93 | @param completion The block invoked (on main thread) when image request completed. 94 | */ 95 | - (void)yy_setImageWithURL:(nullable NSURL *)imageURL 96 | placeholder:(nullable UIImage *)placeholder 97 | options:(YYWebImageOptions)options 98 | manager:(nullable YYWebImageManager *)manager 99 | progress:(nullable YYWebImageProgressBlock)progress 100 | transform:(nullable YYWebImageTransformBlock)transform 101 | completion:(nullable YYWebImageCompletionBlock)completion; 102 | 103 | /** 104 | Cancel the current image request. 105 | */ 106 | - (void)yy_cancelCurrentImageRequest; 107 | 108 | 109 | 110 | #pragma mark - highlight image 111 | 112 | /** 113 | Current highlighted image URL. 114 | 115 | @discussion Set a new value to this property will cancel the previous request 116 | operation and create a new request operation to fetch image. Set nil to clear 117 | the highlighted image and image URL. 118 | */ 119 | @property (nullable, nonatomic, strong) NSURL *yy_highlightedImageURL; 120 | 121 | /** 122 | Set the view's `highlightedImage` with a specified URL. 123 | 124 | @param imageURL The image url (remote or local file path). 125 | @param placeholder The image to be set initially, until the image request finishes. 126 | */ 127 | - (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; 128 | 129 | /** 130 | Set the view's `highlightedImage` with a specified URL. 131 | 132 | @param imageURL The image url (remote or local file path). 133 | @param options The options to use when request the image. 134 | */ 135 | - (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; 136 | 137 | /** 138 | Set the view's `highlightedImage` with a specified URL. 139 | 140 | @param imageURL The image url (remote or local file path). 141 | @param placeholder The image to be set initially, until the image request finishes. 142 | @param options The options to use when request the image. 143 | @param completion The block invoked (on main thread) when image request completed. 144 | */ 145 | - (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL 146 | placeholder:(nullable UIImage *)placeholder 147 | options:(YYWebImageOptions)options 148 | completion:(nullable YYWebImageCompletionBlock)completion; 149 | 150 | /** 151 | Set the view's `highlightedImage` with a specified URL. 152 | 153 | @param imageURL The image url (remote or local file path). 154 | @param placeholder The image to be set initially, until the image request finishes. 155 | @param options The options to use when request the image. 156 | @param progress The block invoked (on main thread) during image request. 157 | @param transform The block invoked (on background thread) to do additional image process. 158 | @param completion The block invoked (on main thread) when image request completed. 159 | */ 160 | - (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL 161 | placeholder:(nullable UIImage *)placeholder 162 | options:(YYWebImageOptions)options 163 | progress:(nullable YYWebImageProgressBlock)progress 164 | transform:(nullable YYWebImageTransformBlock)transform 165 | completion:(nullable YYWebImageCompletionBlock)completion; 166 | 167 | /** 168 | Set the view's `highlightedImage` with a specified URL. 169 | 170 | @param imageURL The image url (remote or local file path). 171 | @param placeholder The image to be set initially, until the image request finishes. 172 | @param options The options to use when request the image. 173 | @param manager The manager to create image request operation. 174 | @param progress The block invoked (on main thread) during image request. 175 | @param transform The block invoked (on background thread) to do additional image process. 176 | @param completion The block invoked (on main thread) when image request completed. 177 | */ 178 | - (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL 179 | placeholder:(nullable UIImage *)placeholder 180 | options:(YYWebImageOptions)options 181 | manager:(nullable YYWebImageManager *)manager 182 | progress:(nullable YYWebImageProgressBlock)progress 183 | transform:(nullable YYWebImageTransformBlock)transform 184 | completion:(nullable YYWebImageCompletionBlock)completion; 185 | 186 | /** 187 | Cancel the current highlighed image request. 188 | */ 189 | - (void)yy_cancelCurrentHighlightedImageRequest; 190 | 191 | @end 192 | 193 | NS_ASSUME_NONNULL_END 194 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/_YYWebImageSetter.h: -------------------------------------------------------------------------------- 1 | // 2 | // _YYWebImageSetter.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/7/15. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | #import 12 | #import 13 | 14 | #if __has_include() 15 | #import 16 | #else 17 | #import "YYWebImageManager.h" 18 | #endif 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | Submits a block for execution on a main queue and waits until the block completes. 24 | */ 25 | static inline void _yy_dispatch_sync_on_main_queue(void (^block)()) { 26 | if (pthread_main_np()) { 27 | block(); 28 | } else { 29 | dispatch_sync(dispatch_get_main_queue(), block); 30 | } 31 | } 32 | 33 | extern NSString *const _YYWebImageFadeAnimationKey; 34 | extern const NSTimeInterval _YYWebImageFadeTime; 35 | extern const NSTimeInterval _YYWebImageProgressiveFadeTime; 36 | 37 | /** 38 | Private class used by web image categories. 39 | Typically, you should not use this class directly. 40 | */ 41 | @interface _YYWebImageSetter : NSObject 42 | /// Current image url. 43 | @property (nullable, nonatomic, readonly) NSURL *imageURL; 44 | /// Current sentinel. 45 | @property (nonatomic, readonly) int32_t sentinel; 46 | 47 | /// Create new operation for web image and return a sentinel value. 48 | - (int32_t)setOperationWithSentinel:(int32_t)sentinel 49 | url:(nullable NSURL *)imageURL 50 | options:(YYWebImageOptions)options 51 | manager:(YYWebImageManager *)manager 52 | progress:(nullable YYWebImageProgressBlock)progress 53 | transform:(nullable YYWebImageTransformBlock)transform 54 | completion:(nullable YYWebImageCompletionBlock)completion; 55 | 56 | /// Cancel and return a sentinel value. The imageURL will be set to nil. 57 | - (int32_t)cancel; 58 | 59 | /// Cancel and return a sentinel value. The imageURL will be set to new value. 60 | - (int32_t)cancelWithNewURL:(nullable NSURL *)imageURL; 61 | 62 | /// A queue to set operation. 63 | + (dispatch_queue_t)setterQueue; 64 | 65 | @end 66 | 67 | NS_ASSUME_NONNULL_END 68 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Categories/_YYWebImageSetter.m: -------------------------------------------------------------------------------- 1 | // 2 | // _YYWebImageSetter.m 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/7/15. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "_YYWebImageSetter.h" 13 | #import "YYWebImageOperation.h" 14 | #import 15 | 16 | NSString *const _YYWebImageFadeAnimationKey = @"YYWebImageFade"; 17 | const NSTimeInterval _YYWebImageFadeTime = 0.2; 18 | const NSTimeInterval _YYWebImageProgressiveFadeTime = 0.4; 19 | 20 | 21 | @implementation _YYWebImageSetter { 22 | dispatch_semaphore_t _lock; 23 | NSURL *_imageURL; 24 | NSOperation *_operation; 25 | int32_t _sentinel; 26 | } 27 | 28 | - (instancetype)init { 29 | self = [super init]; 30 | _lock = dispatch_semaphore_create(1); 31 | return self; 32 | } 33 | 34 | - (NSURL *)imageURL { 35 | dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); 36 | NSURL *imageURL = _imageURL; 37 | dispatch_semaphore_signal(_lock); 38 | return imageURL; 39 | } 40 | 41 | - (void)dealloc { 42 | OSAtomicIncrement32(&_sentinel); 43 | [_operation cancel]; 44 | } 45 | 46 | - (int32_t)setOperationWithSentinel:(int32_t)sentinel 47 | url:(NSURL *)imageURL 48 | options:(YYWebImageOptions)options 49 | manager:(YYWebImageManager *)manager 50 | progress:(YYWebImageProgressBlock)progress 51 | transform:(YYWebImageTransformBlock)transform 52 | completion:(YYWebImageCompletionBlock)completion { 53 | if (sentinel != _sentinel) { 54 | if (completion) completion(nil, imageURL, YYWebImageFromNone, YYWebImageStageCancelled, nil); 55 | return _sentinel; 56 | } 57 | 58 | NSOperation *operation = [manager requestImageWithURL:imageURL options:options progress:progress transform:transform completion:completion]; 59 | if (!operation && completion) { 60 | NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"YYWebImageOperation create failed." }; 61 | completion(nil, imageURL, YYWebImageFromNone, YYWebImageStageFinished, [NSError errorWithDomain:@"com.ibireme.webimage" code:-1 userInfo:userInfo]); 62 | } 63 | 64 | dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); 65 | if (sentinel == _sentinel) { 66 | if (_operation) [_operation cancel]; 67 | _operation = operation; 68 | sentinel = OSAtomicIncrement32(&_sentinel); 69 | } else { 70 | [operation cancel]; 71 | } 72 | dispatch_semaphore_signal(_lock); 73 | return sentinel; 74 | } 75 | 76 | - (int32_t)cancel { 77 | return [self cancelWithNewURL:nil]; 78 | } 79 | 80 | - (int32_t)cancelWithNewURL:(NSURL *)imageURL { 81 | int32_t sentinel; 82 | dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); 83 | if (_operation) { 84 | [_operation cancel]; 85 | _operation = nil; 86 | } 87 | _imageURL = imageURL; 88 | sentinel = OSAtomicIncrement32(&_sentinel); 89 | dispatch_semaphore_signal(_lock); 90 | return sentinel; 91 | } 92 | 93 | + (dispatch_queue_t)setterQueue { 94 | static dispatch_queue_t queue; 95 | static dispatch_once_t onceToken; 96 | dispatch_once(&onceToken, ^{ 97 | queue = dispatch_queue_create("com.ibireme.webimage.setter", DISPATCH_QUEUE_SERIAL); 98 | dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 99 | }); 100 | return queue; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Image/YYAnimatedImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYAnimatedImageView.h 3 | // YYImage 4 | // 5 | // Created by ibireme on 14/10/19. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | An image view for displaying animated image. 18 | 19 | @discussion It is a fully compatible `UIImageView` subclass. 20 | If the `image` or `highlightedImage` property adopt to the `YYAnimatedImage` protocol, 21 | then it can be used to play the multi-frame animation. The animation can also be 22 | controlled with the UIImageView methods `-startAnimating`, `-stopAnimating` and `-isAnimating`. 23 | 24 | This view request the frame data just in time. When the device has enough free memory, 25 | this view may cache some or all future frames in an inner buffer for lower CPU cost. 26 | Buffer size is dynamically adjusted based on the current state of the device memory. 27 | 28 | Sample Code: 29 | 30 | // ani@3x.gif 31 | YYImage *image = [YYImage imageNamed:@"ani"]; 32 | YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image]; 33 | [view addSubView:imageView]; 34 | */ 35 | @interface YYAnimatedImageView : UIImageView 36 | 37 | /** 38 | If the image has more than one frame, set this value to `YES` will automatically 39 | play/stop the animation when the view become visible/invisible. 40 | 41 | The default value is `YES`. 42 | */ 43 | @property (nonatomic) BOOL autoPlayAnimatedImage; 44 | 45 | /** 46 | Index of the currently displayed frame (index from 0). 47 | 48 | Set a new value to this property will cause to display the new frame immediately. 49 | If the new value is invalid, this method has no effect. 50 | 51 | You can add an observer to this property to observe the playing status. 52 | */ 53 | @property (nonatomic) NSUInteger currentAnimatedImageIndex; 54 | 55 | /** 56 | Whether the image view is playing animation currently. 57 | 58 | You can add an observer to this property to observe the playing status. 59 | */ 60 | @property (nonatomic, readonly) BOOL currentIsPlayingAnimation; 61 | 62 | /** 63 | The animation timer's runloop mode, default is `NSRunLoopCommonModes`. 64 | 65 | Set this property to `NSDefaultRunLoopMode` will make the animation pause during 66 | UIScrollView scrolling. 67 | */ 68 | @property (nonatomic, copy) NSString *runloopMode; 69 | 70 | /** 71 | The max size (in bytes) for inner frame buffer size, default is 0 (dynamically). 72 | 73 | When the device has enough free memory, this view will request and decode some or 74 | all future frame image into an inner buffer. If this property's value is 0, then 75 | the max buffer size will be dynamically adjusted based on the current state of 76 | the device free memory. Otherwise, the buffer size will be limited by this value. 77 | 78 | When receive memory warning or app enter background, the buffer will be released 79 | immediately, and may grow back at the right time. 80 | */ 81 | @property (nonatomic) NSUInteger maxBufferSize; 82 | 83 | @end 84 | 85 | 86 | 87 | /** 88 | The YYAnimatedImage protocol declares the required methods for animated image 89 | display with YYAnimatedImageView. 90 | 91 | Subclass a UIImage and implement this protocol, so that instances of that class 92 | can be set to YYAnimatedImageView.image or YYAnimatedImageView.highlightedImage 93 | to display animation. 94 | 95 | See `YYImage` and `YYFrameImage` for example. 96 | */ 97 | @protocol YYAnimatedImage 98 | @required 99 | /// Total animated frame count. 100 | /// It the frame count is less than 1, then the methods below will be ignored. 101 | - (NSUInteger)animatedImageFrameCount; 102 | 103 | /// Animation loop count, 0 means infinite looping. 104 | - (NSUInteger)animatedImageLoopCount; 105 | 106 | /// Bytes per frame (in memory). It may used to optimize memory buffer size. 107 | - (NSUInteger)animatedImageBytesPerFrame; 108 | 109 | /// Returns the frame image from a specified index. 110 | /// This method may be called on background thread. 111 | /// @param index Frame index (zero based). 112 | - (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index; 113 | 114 | /// Returns the frames's duration from a specified index. 115 | /// @param index Frame index (zero based). 116 | - (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index; 117 | 118 | @optional 119 | /// A rectangle in image coordinates defining the subrectangle of the image that 120 | /// will be displayed. The rectangle should not outside the image's bounds. 121 | /// It may used to display sprite animation with a single image (sprite sheet). 122 | - (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index; 123 | @end 124 | 125 | NS_ASSUME_NONNULL_END 126 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Image/YYFrameImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYFrameImage.h 3 | // YYImage 4 | // 5 | // Created by ibireme on 14/12/9. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | #import 16 | #elif __has_include() 17 | #import 18 | #else 19 | #import "YYAnimatedImageView.h" 20 | #endif 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | /** 25 | An image to display frame-based animation. 26 | 27 | @discussion It is a fully compatible `UIImage` subclass. 28 | It only support system image format such as png and jpeg. 29 | The animation can be played by YYAnimatedImageView. 30 | 31 | Sample Code: 32 | 33 | NSArray *paths = @[@"/ani/frame1.png", @"/ani/frame2.png", @"/ani/frame3.png"]; 34 | NSArray *times = @[@0.1, @0.2, @0.1]; 35 | YYFrameImage *image = [YYFrameImage alloc] initWithImagePaths:paths frameDurations:times repeats:YES]; 36 | YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image]; 37 | [view addSubView:imageView]; 38 | */ 39 | @interface YYFrameImage : UIImage 40 | 41 | /** 42 | Create a frame animated image from files. 43 | 44 | @param paths An array of NSString objects, contains the full or 45 | partial path to each image file. 46 | e.g. @[@"/ani/1.png",@"/ani/2.png",@"/ani/3.png"] 47 | 48 | @param oneFrameDuration The duration (in seconds) per frame. 49 | 50 | @param loopCount The animation loop count, 0 means infinite. 51 | 52 | @return An initialized YYFrameImage object, or nil when an error occurs. 53 | */ 54 | - (nullable instancetype)initWithImagePaths:(NSArray *)paths 55 | oneFrameDuration:(NSTimeInterval)oneFrameDuration 56 | loopCount:(NSUInteger)loopCount; 57 | 58 | /** 59 | Create a frame animated image from files. 60 | 61 | @param paths An array of NSString objects, contains the full or 62 | partial path to each image file. 63 | e.g. @[@"/ani/frame1.png",@"/ani/frame2.png",@"/ani/frame3.png"] 64 | 65 | @param frameDurations An array of NSNumber objects, contains the duration (in seconds) per frame. 66 | e.g. @[@0.1, @0.2, @0.3]; 67 | 68 | @param loopCount The animation loop count, 0 means infinite. 69 | 70 | @return An initialized YYFrameImage object, or nil when an error occurs. 71 | */ 72 | - (nullable instancetype)initWithImagePaths:(NSArray *)paths 73 | frameDurations:(NSArray *)frameDurations 74 | loopCount:(NSUInteger)loopCount; 75 | 76 | /** 77 | Create a frame animated image from an array of data. 78 | 79 | @param dataArray An array of NSData objects. 80 | 81 | @param oneFrameDuration The duration (in seconds) per frame. 82 | 83 | @param loopCount The animation loop count, 0 means infinite. 84 | 85 | @return An initialized YYFrameImage object, or nil when an error occurs. 86 | */ 87 | - (nullable instancetype)initWithImageDataArray:(NSArray *)dataArray 88 | oneFrameDuration:(NSTimeInterval)oneFrameDuration 89 | loopCount:(NSUInteger)loopCount; 90 | 91 | /** 92 | Create a frame animated image from an array of data. 93 | 94 | @param dataArray An array of NSData objects. 95 | 96 | @param frameDurations An array of NSNumber objects, contains the duration (in seconds) per frame. 97 | e.g. @[@0.1, @0.2, @0.3]; 98 | 99 | @param loopCount The animation loop count, 0 means infinite. 100 | 101 | @return An initialized YYFrameImage object, or nil when an error occurs. 102 | */ 103 | - (nullable instancetype)initWithImageDataArray:(NSArray *)dataArray 104 | frameDurations:(NSArray *)frameDurations 105 | loopCount:(NSUInteger)loopCount; 106 | 107 | @end 108 | 109 | NS_ASSUME_NONNULL_END 110 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Image/YYFrameImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // YYFrameImage.m 3 | // YYImage 4 | // 5 | // Created by ibireme on 14/12/9. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "YYFrameImage.h" 13 | #import "YYImageCoder.h" 14 | 15 | 16 | /** 17 | Return the path scale. 18 | 19 | e.g. 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
Path Scale
"icon.png" 1
"icon@2x.png" 2
"icon@2.5x.png" 2.5
"icon@2x" 1
"icon@2x..png" 1
"icon@2x.png/" 1
29 | */ 30 | static CGFloat _NSStringPathScale(NSString *string) { 31 | if (string.length == 0 || [string hasSuffix:@"/"]) return 1; 32 | NSString *name = string.stringByDeletingPathExtension; 33 | __block CGFloat scale = 1; 34 | 35 | NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines error:nil]; 36 | [pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 37 | if (result.range.location >= 3) { 38 | scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue; 39 | } 40 | }]; 41 | 42 | return scale; 43 | } 44 | 45 | 46 | 47 | @implementation YYFrameImage { 48 | NSUInteger _loopCount; 49 | NSUInteger _oneFrameBytes; 50 | NSArray *_imagePaths; 51 | NSArray *_imageDatas; 52 | NSArray *_frameDurations; 53 | } 54 | 55 | - (instancetype)initWithImagePaths:(NSArray *)paths oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount { 56 | NSMutableArray *durations = [NSMutableArray new]; 57 | for (int i = 0, max = (int)paths.count; i < max; i++) { 58 | [durations addObject:@(oneFrameDuration)]; 59 | } 60 | return [self initWithImagePaths:paths frameDurations:durations loopCount:loopCount]; 61 | } 62 | 63 | - (instancetype)initWithImagePaths:(NSArray *)paths frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount { 64 | if (paths.count == 0) return nil; 65 | if (paths.count != frameDurations.count) return nil; 66 | 67 | NSString *firstPath = paths[0]; 68 | NSData *firstData = [NSData dataWithContentsOfFile:firstPath]; 69 | CGFloat scale = _NSStringPathScale(firstPath); 70 | UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded]; 71 | self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp]; 72 | if (!self) return nil; 73 | long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage); 74 | _oneFrameBytes = (NSUInteger)frameByte; 75 | _imagePaths = paths.copy; 76 | _frameDurations = frameDurations.copy; 77 | _loopCount = loopCount; 78 | 79 | return self; 80 | } 81 | 82 | - (instancetype)initWithImageDataArray:(NSArray *)dataArray oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount { 83 | NSMutableArray *durations = [NSMutableArray new]; 84 | for (int i = 0, max = (int)dataArray.count; i < max; i++) { 85 | [durations addObject:@(oneFrameDuration)]; 86 | } 87 | return [self initWithImageDataArray:dataArray frameDurations:durations loopCount:loopCount]; 88 | } 89 | 90 | - (instancetype)initWithImageDataArray:(NSArray *)dataArray frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount { 91 | if (dataArray.count == 0) return nil; 92 | if (dataArray.count != frameDurations.count) return nil; 93 | 94 | NSData *firstData = dataArray[0]; 95 | CGFloat scale = [UIScreen mainScreen].scale; 96 | UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded]; 97 | self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp]; 98 | if (!self) return nil; 99 | long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage); 100 | _oneFrameBytes = (NSUInteger)frameByte; 101 | _imageDatas = dataArray.copy; 102 | _frameDurations = frameDurations.copy; 103 | _loopCount = loopCount; 104 | 105 | return self; 106 | } 107 | 108 | #pragma mark - YYAnimtedImage 109 | 110 | - (NSUInteger)animatedImageFrameCount { 111 | if (_imagePaths) { 112 | return _imagePaths.count; 113 | } else if (_imageDatas) { 114 | return _imageDatas.count; 115 | } else { 116 | return 1; 117 | } 118 | } 119 | 120 | - (NSUInteger)animatedImageLoopCount { 121 | return _loopCount; 122 | } 123 | 124 | - (NSUInteger)animatedImageBytesPerFrame { 125 | return _oneFrameBytes; 126 | } 127 | 128 | - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { 129 | if (_imagePaths) { 130 | if (index >= _imagePaths.count) return nil; 131 | NSString *path = _imagePaths[index]; 132 | CGFloat scale = _NSStringPathScale(path); 133 | NSData *data = [NSData dataWithContentsOfFile:path]; 134 | return [[UIImage imageWithData:data scale:scale] yy_imageByDecoded]; 135 | } else if (_imageDatas) { 136 | if (index >= _imageDatas.count) return nil; 137 | NSData *data = _imageDatas[index]; 138 | return [[UIImage imageWithData:data scale:[UIScreen mainScreen].scale] yy_imageByDecoded]; 139 | } else { 140 | return index == 0 ? self : nil; 141 | } 142 | } 143 | 144 | - (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index { 145 | if (index >= _frameDurations.count) return 0; 146 | NSNumber *num = _frameDurations[index]; 147 | return [num doubleValue]; 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Image/YYImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYImage.h 3 | // YYImage 4 | // 5 | // Created by ibireme on 14/10/20. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | FOUNDATION_EXPORT double YYImageVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char YYImageVersionString[]; 17 | #import 18 | #import 19 | #import 20 | #import 21 | #elif __has_include() 22 | #import 23 | #import 24 | #import 25 | #import 26 | #else 27 | #import "YYFrameImage.h" 28 | #import "YYSpriteSheetImage.h" 29 | #import "YYImageCoder.h" 30 | #import "YYAnimatedImageView.h" 31 | #endif 32 | 33 | NS_ASSUME_NONNULL_BEGIN 34 | 35 | 36 | /** 37 | A YYImage object is a high-level way to display animated image data. 38 | 39 | @discussion It is a fully compatible `UIImage` subclass. It extends the UIImage 40 | to support animated WebP, APNG and GIF format image data decoding. It also 41 | support NSCoding protocol to archive and unarchive multi-frame image data. 42 | 43 | If the image is created from multi-frame image data, and you want to play the 44 | animation, try replace UIImageView with `YYAnimatedImageView`. 45 | 46 | Sample Code: 47 | 48 | // animation@3x.webp 49 | YYImage *image = [YYImage imageNamed:@"animation.webp"]; 50 | YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image]; 51 | [view addSubView:imageView]; 52 | 53 | */ 54 | @interface YYImage : UIImage 55 | 56 | + (nullable YYImage *)imageNamed:(NSString *)name; // no cache! 57 | + (nullable YYImage *)imageWithContentsOfFile:(NSString *)path; 58 | + (nullable YYImage *)imageWithData:(NSData *)data; 59 | + (nullable YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale; 60 | 61 | /** 62 | If the image is created from data or file, then the value indicates the data type. 63 | */ 64 | @property (nonatomic, readonly) YYImageType animatedImageType; 65 | 66 | /** 67 | If the image is created from animated image data (multi-frame GIF/APNG/WebP), 68 | this property stores the original image data. 69 | */ 70 | @property (nullable, nonatomic, readonly) NSData *animatedImageData; 71 | 72 | /** 73 | The total memory usage (in bytes) if all frame images was loaded into memory. 74 | The value is 0 if the image is not created from a multi-frame image data. 75 | */ 76 | @property (nonatomic, readonly) NSUInteger animatedImageMemorySize; 77 | 78 | /** 79 | Preload all frame image to memory. 80 | 81 | @discussion Set this property to `YES` will block the calling thread to decode 82 | all animation frame image to memory, set to `NO` will release the preloaded frames. 83 | If the image is shared by lots of image views (such as emoticon), preload all 84 | frames will reduce the CPU cost. 85 | 86 | See `animatedImageMemorySize` for memory cost. 87 | */ 88 | @property (nonatomic) BOOL preloadAllAnimatedImageFrames; 89 | 90 | @end 91 | 92 | NS_ASSUME_NONNULL_END 93 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Image/YYImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // YYImage.m 3 | // YYImage 4 | // 5 | // Created by ibireme on 14/10/20. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "YYImage.h" 13 | 14 | /** 15 | An array of NSNumber objects, shows the best order for path scale search. 16 | e.g. iPhone3GS:@[@1,@2,@3] iPhone5:@[@2,@3,@1] iPhone6 Plus:@[@3,@2,@1] 17 | */ 18 | static NSArray *_NSBundlePreferredScales() { 19 | static NSArray *scales; 20 | static dispatch_once_t onceToken; 21 | dispatch_once(&onceToken, ^{ 22 | CGFloat screenScale = [UIScreen mainScreen].scale; 23 | if (screenScale <= 1) { 24 | scales = @[@1,@2,@3]; 25 | } else if (screenScale <= 2) { 26 | scales = @[@2,@3,@1]; 27 | } else { 28 | scales = @[@3,@2,@1]; 29 | } 30 | }); 31 | return scales; 32 | } 33 | 34 | /** 35 | Add scale modifier to the file name (without path extension), 36 | From @"name" to @"name@2x". 37 | 38 | e.g. 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
Before After(scale:2)
"icon" "icon@2x"
"icon " "icon @2x"
"icon.top" "icon.top@2x"
"/p/name" "/p/name@2x"
"/path/" "/path/"
47 | 48 | @param scale Resource scale. 49 | @return String by add scale modifier, or just return if it's not end with file name. 50 | */ 51 | static NSString *_NSStringByAppendingNameScale(NSString *string, CGFloat scale) { 52 | if (!string) return nil; 53 | if (fabs(scale - 1) <= __FLT_EPSILON__ || string.length == 0 || [string hasSuffix:@"/"]) return string.copy; 54 | return [string stringByAppendingFormat:@"@%@x", @(scale)]; 55 | } 56 | 57 | /** 58 | Return the path scale. 59 | 60 | e.g. 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
Path Scale
"icon.png" 1
"icon@2x.png" 2
"icon@2.5x.png" 2.5
"icon@2x" 1
"icon@2x..png" 1
"icon@2x.png/" 1
70 | */ 71 | static CGFloat _NSStringPathScale(NSString *string) { 72 | if (string.length == 0 || [string hasSuffix:@"/"]) return 1; 73 | NSString *name = string.stringByDeletingPathExtension; 74 | __block CGFloat scale = 1; 75 | 76 | NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines error:nil]; 77 | [pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 78 | if (result.range.location >= 3) { 79 | scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue; 80 | } 81 | }]; 82 | 83 | return scale; 84 | } 85 | 86 | 87 | @implementation YYImage { 88 | YYImageDecoder *_decoder; 89 | NSArray *_preloadedFrames; 90 | dispatch_semaphore_t _preloadedLock; 91 | NSUInteger _bytesPerFrame; 92 | } 93 | 94 | + (YYImage *)imageNamed:(NSString *)name { 95 | if (name.length == 0) return nil; 96 | if ([name hasSuffix:@"/"]) return nil; 97 | 98 | NSString *res = name.stringByDeletingPathExtension; 99 | NSString *ext = name.pathExtension; 100 | NSString *path = nil; 101 | CGFloat scale = 1; 102 | 103 | // If no extension, guess by system supported (same as UIImage). 104 | NSArray *exts = ext.length > 0 ? @[ext] : @[@"", @"png", @"jpeg", @"jpg", @"gif", @"webp", @"apng"]; 105 | NSArray *scales = _NSBundlePreferredScales(); 106 | for (int s = 0; s < scales.count; s++) { 107 | scale = ((NSNumber *)scales[s]).floatValue; 108 | NSString *scaledName = _NSStringByAppendingNameScale(res, scale); 109 | for (NSString *e in exts) { 110 | path = [[NSBundle mainBundle] pathForResource:scaledName ofType:e]; 111 | if (path) break; 112 | } 113 | if (path) break; 114 | } 115 | if (path.length == 0) return nil; 116 | 117 | NSData *data = [NSData dataWithContentsOfFile:path]; 118 | if (data.length == 0) return nil; 119 | 120 | return [[self alloc] initWithData:data scale:scale]; 121 | } 122 | 123 | + (YYImage *)imageWithContentsOfFile:(NSString *)path { 124 | return [[self alloc] initWithContentsOfFile:path]; 125 | } 126 | 127 | + (YYImage *)imageWithData:(NSData *)data { 128 | return [[self alloc] initWithData:data]; 129 | } 130 | 131 | + (YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale { 132 | return [[self alloc] initWithData:data scale:scale]; 133 | } 134 | 135 | - (instancetype)initWithContentsOfFile:(NSString *)path { 136 | NSData *data = [NSData dataWithContentsOfFile:path]; 137 | return [self initWithData:data scale:_NSStringPathScale(path)]; 138 | } 139 | 140 | - (instancetype)initWithData:(NSData *)data { 141 | return [self initWithData:data scale:1]; 142 | } 143 | 144 | - (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale { 145 | if (data.length == 0) return nil; 146 | if (scale <= 0) scale = [UIScreen mainScreen].scale; 147 | _preloadedLock = dispatch_semaphore_create(1); 148 | @autoreleasepool { 149 | YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:scale]; 150 | YYImageFrame *frame = [decoder frameAtIndex:0 decodeForDisplay:YES]; 151 | UIImage *image = frame.image; 152 | if (!image) return nil; 153 | self = [self initWithCGImage:image.CGImage scale:decoder.scale orientation:image.imageOrientation]; 154 | if (!self) return nil; 155 | _animatedImageType = decoder.type; 156 | if (decoder.frameCount > 1) { 157 | _decoder = decoder; 158 | _bytesPerFrame = CGImageGetBytesPerRow(image.CGImage) * CGImageGetHeight(image.CGImage); 159 | _animatedImageMemorySize = _bytesPerFrame * decoder.frameCount; 160 | } 161 | self.yy_isDecodedForDisplay = YES; 162 | } 163 | return self; 164 | } 165 | 166 | - (NSData *)animatedImageData { 167 | return _decoder.data; 168 | } 169 | 170 | - (void)setPreloadAllAnimatedImageFrames:(BOOL)preloadAllAnimatedImageFrames { 171 | if (_preloadAllAnimatedImageFrames != preloadAllAnimatedImageFrames) { 172 | if (preloadAllAnimatedImageFrames && _decoder.frameCount > 0) { 173 | NSMutableArray *frames = [NSMutableArray new]; 174 | for (NSUInteger i = 0, max = _decoder.frameCount; i < max; i++) { 175 | UIImage *img = [self animatedImageFrameAtIndex:i]; 176 | if (img) { 177 | [frames addObject:img]; 178 | } else { 179 | [frames addObject:[NSNull null]]; 180 | } 181 | } 182 | dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); 183 | _preloadedFrames = frames; 184 | dispatch_semaphore_signal(_preloadedLock); 185 | } else { 186 | dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); 187 | _preloadedFrames = nil; 188 | dispatch_semaphore_signal(_preloadedLock); 189 | } 190 | } 191 | } 192 | 193 | #pragma mark - protocol NSCoding 194 | 195 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 196 | NSNumber *scale = [aDecoder decodeObjectForKey:@"YYImageScale"]; 197 | NSData *data = [aDecoder decodeObjectForKey:@"YYImageData"]; 198 | if (data.length) { 199 | self = [self initWithData:data scale:scale.doubleValue]; 200 | } else { 201 | self = [super initWithCoder:aDecoder]; 202 | } 203 | return self; 204 | } 205 | 206 | - (void)encodeWithCoder:(NSCoder *)aCoder { 207 | if (_decoder.data.length) { 208 | [aCoder encodeObject:@(self.scale) forKey:@"YYImageScale"]; 209 | [aCoder encodeObject:_decoder.data forKey:@"YYImageData"]; 210 | } else { 211 | [super encodeWithCoder:aCoder]; // Apple use UIImagePNGRepresentation() to encode UIImage. 212 | } 213 | } 214 | 215 | #pragma mark - protocol YYAnimatedImage 216 | 217 | - (NSUInteger)animatedImageFrameCount { 218 | return _decoder.frameCount; 219 | } 220 | 221 | - (NSUInteger)animatedImageLoopCount { 222 | return _decoder.loopCount; 223 | } 224 | 225 | - (NSUInteger)animatedImageBytesPerFrame { 226 | return _bytesPerFrame; 227 | } 228 | 229 | - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { 230 | if (index >= _decoder.frameCount) return nil; 231 | dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); 232 | UIImage *image = _preloadedFrames[index]; 233 | dispatch_semaphore_signal(_preloadedLock); 234 | if (image) return image == (id)[NSNull null] ? nil : image; 235 | return [_decoder frameAtIndex:index decodeForDisplay:YES].image; 236 | } 237 | 238 | - (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index { 239 | NSTimeInterval duration = [_decoder frameDurationAtIndex:index]; 240 | 241 | /* 242 | http://opensource.apple.com/source/WebCore/WebCore-7600.1.25/platform/graphics/cg/ImageSourceCG.cpp 243 | Many annoying ads specify a 0 duration to make an image flash as quickly as 244 | possible. We follow Safari and Firefox's behavior and use a duration of 100 ms 245 | for any frames that specify a duration of <= 10 ms. 246 | See and for more information. 247 | 248 | See also: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser. 249 | */ 250 | if (duration < 0.011f) return 0.100f; 251 | return duration; 252 | } 253 | 254 | @end 255 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Image/YYSpriteSheetImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYSpriteImage.h 3 | // YYImage 4 | // 5 | // Created by ibireme on 15/4/21. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | #import 16 | #elif __has_include() 17 | #import 18 | #else 19 | #import "YYAnimatedImageView.h" 20 | #endif 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | /** 25 | An image to display sprite sheet animation. 26 | 27 | @discussion It is a fully compatible `UIImage` subclass. 28 | The animation can be played by YYAnimatedImageView. 29 | 30 | Sample Code: 31 | 32 | // 8 * 12 sprites in a single sheet image 33 | UIImage *spriteSheet = [UIImage imageNamed:@"sprite-sheet"]; 34 | NSMutableArray *contentRects = [NSMutableArray new]; 35 | NSMutableArray *durations = [NSMutableArray new]; 36 | for (int j = 0; j < 12; j++) { 37 | for (int i = 0; i < 8; i++) { 38 | CGRect rect; 39 | rect.size = CGSizeMake(img.size.width / 8, img.size.height / 12); 40 | rect.origin.x = img.size.width / 8 * i; 41 | rect.origin.y = img.size.height / 12 * j; 42 | [contentRects addObject:[NSValue valueWithCGRect:rect]]; 43 | [durations addObject:@(1 / 60.0)]; 44 | } 45 | } 46 | YYSpriteSheetImage *sprite; 47 | sprite = [[YYSpriteSheetImage alloc] initWithSpriteSheetImage:img 48 | contentRects:contentRects 49 | frameDurations:durations 50 | loopCount:0]; 51 | YYAnimatedImageView *imgView = [YYAnimatedImageView new]; 52 | imgView.size = CGSizeMake(img.size.width / 8, img.size.height / 12); 53 | imgView.image = sprite; 54 | 55 | 56 | 57 | @discussion It can also be used to display single frame in sprite sheet image. 58 | Sample Code: 59 | 60 | YYSpriteSheetImage *sheet = ...; 61 | UIImageView *imageView = ...; 62 | imageView.image = sheet; 63 | imageView.layer.contentsRect = [sheet contentsRectForCALayerAtIndex:6]; 64 | 65 | */ 66 | @interface YYSpriteSheetImage : UIImage 67 | 68 | /** 69 | Creates and returns an image object. 70 | 71 | @param image The sprite sheet image (contains all frames). 72 | 73 | @param contentRects The sprite sheet image frame rects in the image coordinates. 74 | The rectangle should not outside the image's bounds. The objects in this array 75 | should be created with [NSValue valueWithCGRect:]. 76 | 77 | @param frameDurations The sprite sheet image frame's durations in seconds. 78 | The objects in this array should be NSNumber. 79 | 80 | @param loopCount Animation loop count, 0 means infinite looping. 81 | 82 | @return An image object, or nil if an error occurs. 83 | */ 84 | - (nullable instancetype)initWithSpriteSheetImage:(UIImage *)image 85 | contentRects:(NSArray *)contentRects 86 | frameDurations:(NSArray *)frameDurations 87 | loopCount:(NSUInteger)loopCount; 88 | 89 | @property (nonatomic, readonly) NSArray *contentRects; 90 | @property (nonatomic, readonly) NSArray *frameDurations; 91 | @property (nonatomic, readonly) NSUInteger loopCount; 92 | 93 | /** 94 | Get the contents rect for CALayer. 95 | See "contentsRect" property in CALayer for more information. 96 | 97 | @param index Index of frame. 98 | @return Contents Rect. 99 | */ 100 | - (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index; 101 | 102 | @end 103 | 104 | NS_ASSUME_NONNULL_END 105 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/Image/YYSpriteSheetImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // YYSpriteImage.m 3 | // YYImage 4 | // 5 | // Created by ibireme on 15/4/21. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "YYSpriteSheetImage.h" 13 | 14 | @implementation YYSpriteSheetImage 15 | 16 | - (instancetype)initWithSpriteSheetImage:(UIImage *)image 17 | contentRects:(NSArray *)contentRects 18 | frameDurations:(NSArray *)frameDurations 19 | loopCount:(NSUInteger)loopCount { 20 | if (!image.CGImage) return nil; 21 | if (contentRects.count < 1 || frameDurations.count < 1) return nil; 22 | if (contentRects.count != frameDurations.count) return nil; 23 | 24 | self = [super initWithCGImage:image.CGImage scale:image.scale orientation:image.imageOrientation]; 25 | if (!self) return nil; 26 | 27 | _contentRects = contentRects.copy; 28 | _frameDurations = frameDurations.copy; 29 | _loopCount = loopCount; 30 | return self; 31 | } 32 | 33 | - (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index { 34 | CGRect layerRect = CGRectMake(0, 0, 1, 1); 35 | if (index >= _contentRects.count) return layerRect; 36 | 37 | CGSize imageSize = self.size; 38 | CGRect rect = [self animatedImageContentsRectAtIndex:index]; 39 | if (imageSize.width > 0.01 && imageSize.height > 0.01) { 40 | layerRect.origin.x = rect.origin.x / imageSize.width; 41 | layerRect.origin.y = rect.origin.y / imageSize.height; 42 | layerRect.size.width = rect.size.width / imageSize.width; 43 | layerRect.size.height = rect.size.height / imageSize.height; 44 | layerRect = CGRectIntersection(layerRect, CGRectMake(0, 0, 1, 1)); 45 | if (CGRectIsNull(layerRect) || CGRectIsEmpty(layerRect)) { 46 | layerRect = CGRectMake(0, 0, 1, 1); 47 | } 48 | } 49 | return layerRect; 50 | } 51 | 52 | #pragma mark @protocol YYAnimatedImage 53 | 54 | - (NSUInteger)animatedImageFrameCount { 55 | return _contentRects.count; 56 | } 57 | 58 | - (NSUInteger)animatedImageLoopCount { 59 | return _loopCount; 60 | } 61 | 62 | - (NSUInteger)animatedImageBytesPerFrame { 63 | return 0; 64 | } 65 | 66 | - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { 67 | return self; 68 | } 69 | 70 | - (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index { 71 | if (index >= _frameDurations.count) return 0; 72 | return ((NSNumber *)_frameDurations[index]).doubleValue; 73 | } 74 | 75 | - (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index { 76 | if (index >= _contentRects.count) return CGRectZero; 77 | return ((NSValue *)_contentRects[index]).CGRectValue; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/YYImageCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYImageCache.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/15. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | @class YYMemoryCache, YYDiskCache; 15 | 16 | NS_ASSUME_NONNULL_BEGIN 17 | 18 | /// Image cache type 19 | typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { 20 | /// No value. 21 | YYImageCacheTypeNone = 0, 22 | 23 | /// Get/store image with memory cache. 24 | YYImageCacheTypeMemory = 1 << 0, 25 | 26 | /// Get/store image with disk cache. 27 | YYImageCacheTypeDisk = 1 << 1, 28 | 29 | /// Get/store image with both memory cache and disk cache. 30 | YYImageCacheTypeAll = YYImageCacheTypeMemory | YYImageCacheTypeDisk, 31 | }; 32 | 33 | 34 | /** 35 | YYImageCache is a cache that stores UIImage and image data based on memory cache and disk cache. 36 | 37 | @discussion The disk cache will try to protect the original image data: 38 | 39 | * If the original image is still image, it will be saved as png/jpeg file based on alpha information. 40 | * If the original image is animated gif, apng or webp, it will be saved as original format. 41 | * If the original image's scale is not 1, the scale value will be saved as extended data. 42 | 43 | Although UIImage can be serialized with NSCoding protocol, but it's not a good idea: 44 | Apple actually use UIImagePNGRepresentation() to encode all kind of image, it may 45 | lose the original multi-frame data. The result is packed to plist file and cannot 46 | view with photo viewer directly. If the image has no alpha channel, using JPEG 47 | instead of PNG can save more disk size and encoding/decoding time. 48 | */ 49 | @interface YYImageCache : NSObject 50 | 51 | #pragma mark - Attribute 52 | ///============================================================================= 53 | /// @name Attribute 54 | ///============================================================================= 55 | 56 | /** The name of the cache. Default is nil. */ 57 | @property (nullable, copy) NSString *name; 58 | 59 | /** The underlying memory cache. see `YYMemoryCache` for more information.*/ 60 | @property (strong, readonly) YYMemoryCache *memoryCache; 61 | 62 | /** The underlying disk cache. see `YYDiskCache` for more information.*/ 63 | @property (strong, readonly) YYDiskCache *diskCache; 64 | 65 | /** 66 | Whether decode animated image when fetch image from disk cache. Default is YES. 67 | 68 | @discussion When fetch image from disk cache, it will use 'YYImage' to decode 69 | animated image such as WebP/APNG/GIF. Set to 'NO' to ignore animated image. 70 | */ 71 | @property BOOL allowAnimatedImage; 72 | 73 | /** 74 | Whether decode the image to memory bitmap. Default is YES. 75 | 76 | @discussion If the value is YES, then the image will be decoded to memory bitmap 77 | for better display performance, but may cost more memory. 78 | */ 79 | @property BOOL decodeForDisplay; 80 | 81 | 82 | #pragma mark - Initializer 83 | ///============================================================================= 84 | /// @name Initializer 85 | ///============================================================================= 86 | - (instancetype)init UNAVAILABLE_ATTRIBUTE; 87 | + (instancetype)new UNAVAILABLE_ATTRIBUTE; 88 | 89 | /** 90 | Returns global shared image cache instance. 91 | @return The singleton YYImageCache instance. 92 | */ 93 | + (instancetype)sharedCache; 94 | 95 | /** 96 | The designated initializer. Multiple instances with the same path will make the 97 | cache unstable. 98 | 99 | @param path Full path of a directory in which the cache will write data. 100 | Once initialized you should not read and write to this directory. 101 | @result A new cache object, or nil if an error occurs. 102 | */ 103 | - (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; 104 | 105 | 106 | #pragma mark - Access Methods 107 | ///============================================================================= 108 | /// @name Access Methods 109 | ///============================================================================= 110 | 111 | /** 112 | Sets the image with the specified key in the cache (both memory and disk). 113 | This method returns immediately and executes the store operation in background. 114 | 115 | @param image The image to be stored in the cache. If nil, this method has no effect. 116 | @param key The key with which to associate the image. If nil, this method has no effect. 117 | */ 118 | - (void)setImage:(UIImage *)image forKey:(NSString *)key; 119 | 120 | /** 121 | Sets the image with the specified key in the cache. 122 | This method returns immediately and executes the store operation in background. 123 | 124 | @discussion If the `type` contain `YYImageCacheTypeMemory`, then the `image` will 125 | be stored in the memory cache; `imageData` will be used instead if `image` is nil. 126 | If the `type` contain `YYImageCacheTypeDisk`, then the `imageData` will 127 | be stored in the disk cache; `image` will be used instead if `imageData` is nil. 128 | 129 | @param image The image to be stored in the cache. 130 | @param imageData The image data to be stored in the cache. 131 | @param key The key with which to associate the image. If nil, this method has no effect. 132 | @param type The cache type to store image. 133 | */ 134 | - (void)setImage:(nullable UIImage *)image 135 | imageData:(nullable NSData *)imageData 136 | forKey:(NSString *)key 137 | withType:(YYImageCacheType)type; 138 | 139 | /** 140 | Removes the image of the specified key in the cache (both memory and disk). 141 | This method returns immediately and executes the remove operation in background. 142 | 143 | @param key The key identifying the image to be removed. If nil, this method has no effect. 144 | */ 145 | - (void)removeImageForKey:(NSString *)key; 146 | 147 | /** 148 | Removes the image of the specified key in the cache. 149 | This method returns immediately and executes the remove operation in background. 150 | 151 | @param key The key identifying the image to be removed. If nil, this method has no effect. 152 | @param type The cache type to remove image. 153 | */ 154 | - (void)removeImageForKey:(NSString *)key withType:(YYImageCacheType)type; 155 | 156 | /** 157 | Returns a Boolean value that indicates whether a given key is in cache. 158 | If the image is not in memory, this method may blocks the calling thread until 159 | file read finished. 160 | 161 | @param key A string identifying the image. If nil, just return NO. 162 | @return Whether the image is in cache. 163 | */ 164 | - (BOOL)containsImageForKey:(NSString *)key; 165 | 166 | /** 167 | Returns a Boolean value that indicates whether a given key is in cache. 168 | If the image is not in memory and the `type` contains `YYImageCacheTypeDisk`, 169 | this method may blocks the calling thread until file read finished. 170 | 171 | @param key A string identifying the image. If nil, just return NO. 172 | @param type The cache type. 173 | @return Whether the image is in cache. 174 | */ 175 | - (BOOL)containsImageForKey:(NSString *)key withType:(YYImageCacheType)type; 176 | 177 | /** 178 | Returns the image associated with a given key. 179 | If the image is not in memory, this method may blocks the calling thread until 180 | file read finished. 181 | 182 | @param key A string identifying the image. If nil, just return nil. 183 | @return The image associated with key, or nil if no image is associated with key. 184 | */ 185 | - (nullable UIImage *)getImageForKey:(NSString *)key; 186 | 187 | /** 188 | Returns the image associated with a given key. 189 | If the image is not in memory and the `type` contains `YYImageCacheTypeDisk`, 190 | this method may blocks the calling thread until file read finished. 191 | 192 | @param key A string identifying the image. If nil, just return nil. 193 | @return The image associated with key, or nil if no image is associated with key. 194 | */ 195 | - (nullable UIImage *)getImageForKey:(NSString *)key withType:(YYImageCacheType)type; 196 | 197 | /** 198 | Asynchronously get the image associated with a given key. 199 | 200 | @param key A string identifying the image. If nil, just return nil. 201 | @param type The cache type. 202 | @param block A completion block which will be called on main thread. 203 | */ 204 | - (void)getImageForKey:(NSString *)key 205 | withType:(YYImageCacheType)type 206 | withBlock:(void(^)(UIImage * _Nullable image, YYImageCacheType type))block; 207 | 208 | /** 209 | Returns the image data associated with a given key. 210 | This method may blocks the calling thread until file read finished. 211 | 212 | @param key A string identifying the image. If nil, just return nil. 213 | @return The image data associated with key, or nil if no image is associated with key. 214 | */ 215 | - (nullable NSData *)getImageDataForKey:(NSString *)key; 216 | 217 | /** 218 | Asynchronously get the image data associated with a given key. 219 | 220 | @param key A string identifying the image. If nil, just return nil. 221 | @param block A completion block which will be called on main thread. 222 | */ 223 | - (void)getImageDataForKey:(NSString *)key 224 | withBlock:(void(^)(NSData * _Nullable imageData))block; 225 | 226 | @end 227 | 228 | NS_ASSUME_NONNULL_END 229 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/YYImageCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // YYImageCache.m 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/15. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "YYImageCache.h" 13 | #import "YYImage.h" 14 | #import "UIImage+YYWebImage.h" 15 | 16 | #if __has_include() 17 | #import 18 | #else 19 | #import "YYImage.h" 20 | #endif 21 | 22 | #if __has_include() 23 | #import 24 | #else 25 | #import "YYCache.h" 26 | #endif 27 | 28 | 29 | 30 | static inline dispatch_queue_t YYImageCacheIOQueue() { 31 | return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 32 | } 33 | 34 | static inline dispatch_queue_t YYImageCacheDecodeQueue() { 35 | return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); 36 | } 37 | 38 | 39 | @interface YYImageCache () 40 | - (NSUInteger)imageCost:(UIImage *)image; 41 | - (UIImage *)imageFromData:(NSData *)data; 42 | @end 43 | 44 | 45 | @implementation YYImageCache 46 | 47 | - (NSUInteger)imageCost:(UIImage *)image { 48 | CGImageRef cgImage = image.CGImage; 49 | if (!cgImage) return 1; 50 | CGFloat height = CGImageGetHeight(cgImage); 51 | size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); 52 | NSUInteger cost = bytesPerRow * height; 53 | if (cost == 0) cost = 1; 54 | return cost; 55 | } 56 | 57 | - (UIImage *)imageFromData:(NSData *)data { 58 | NSData *scaleData = [YYDiskCache getExtendedDataFromObject:data]; 59 | CGFloat scale = 0; 60 | if (scaleData) { 61 | scale = ((NSNumber *)[NSKeyedUnarchiver unarchiveObjectWithData:scaleData]).doubleValue; 62 | } 63 | if (scale <= 0) scale = [UIScreen mainScreen].scale; 64 | UIImage *image; 65 | if (_allowAnimatedImage) { 66 | image = [[YYImage alloc] initWithData:data scale:scale]; 67 | if (_decodeForDisplay) image = [image yy_imageByDecoded]; 68 | } else { 69 | YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:scale]; 70 | image = [decoder frameAtIndex:0 decodeForDisplay:_decodeForDisplay].image; 71 | } 72 | return image; 73 | } 74 | 75 | #pragma mark Public 76 | 77 | + (instancetype)sharedCache { 78 | static YYImageCache *cache = nil; 79 | static dispatch_once_t onceToken; 80 | dispatch_once(&onceToken, ^{ 81 | NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, 82 | NSUserDomainMask, YES) firstObject]; 83 | cachePath = [cachePath stringByAppendingPathComponent:@"com.ibireme.yykit"]; 84 | cachePath = [cachePath stringByAppendingPathComponent:@"images"]; 85 | cache = [[self alloc] initWithPath:cachePath]; 86 | }); 87 | return cache; 88 | } 89 | 90 | - (instancetype)init { 91 | @throw [NSException exceptionWithName:@"YYImageCache init error" reason:@"YYImageCache must be initialized with a path. Use 'initWithPath:' instead." userInfo:nil]; 92 | return [self initWithPath:@""]; 93 | } 94 | 95 | - (instancetype)initWithPath:(NSString *)path { 96 | YYMemoryCache *memoryCache = [YYMemoryCache new]; 97 | memoryCache.shouldRemoveAllObjectsOnMemoryWarning = YES; 98 | memoryCache.shouldRemoveAllObjectsWhenEnteringBackground = YES; 99 | memoryCache.countLimit = NSUIntegerMax; 100 | memoryCache.costLimit = NSUIntegerMax; 101 | memoryCache.ageLimit = 12 * 60 * 60; 102 | 103 | YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path]; 104 | diskCache.customArchiveBlock = ^(id object) { return (NSData *)object; }; 105 | diskCache.customUnarchiveBlock = ^(NSData *data) { return (id)data; }; 106 | if (!memoryCache || !diskCache) return nil; 107 | 108 | self = [super init]; 109 | _memoryCache = memoryCache; 110 | _diskCache = diskCache; 111 | _allowAnimatedImage = YES; 112 | _decodeForDisplay = YES; 113 | return self; 114 | } 115 | 116 | - (void)setImage:(UIImage *)image forKey:(NSString *)key { 117 | [self setImage:image imageData:nil forKey:key withType:YYImageCacheTypeAll]; 118 | } 119 | 120 | - (void)setImage:(UIImage *)image imageData:(NSData *)imageData forKey:(NSString *)key withType:(YYImageCacheType)type { 121 | if (!key || (image == nil && imageData.length == 0)) return; 122 | 123 | __weak typeof(self) _self = self; 124 | if (type & YYImageCacheTypeMemory) { // add to memory cache 125 | if (image) { 126 | if (image.yy_isDecodedForDisplay) { 127 | [_memoryCache setObject:image forKey:key withCost:[_self imageCost:image]]; 128 | } else { 129 | dispatch_async(YYImageCacheDecodeQueue(), ^{ 130 | __strong typeof(_self) self = _self; 131 | if (!self) return; 132 | [self.memoryCache setObject:[image yy_imageByDecoded] forKey:key withCost:[self imageCost:image]]; 133 | }); 134 | } 135 | } else if (imageData) { 136 | dispatch_async(YYImageCacheDecodeQueue(), ^{ 137 | __strong typeof(_self) self = _self; 138 | if (!self) return; 139 | UIImage *newImage = [self imageFromData:imageData]; 140 | [self.memoryCache setObject:newImage forKey:key withCost:[self imageCost:newImage]]; 141 | }); 142 | } 143 | } 144 | if (type & YYImageCacheTypeDisk) { // add to disk cache 145 | if (imageData) { 146 | if (image) { 147 | [YYDiskCache setExtendedData:[NSKeyedArchiver archivedDataWithRootObject:@(image.scale)] toObject:imageData]; 148 | } 149 | [_diskCache setObject:imageData forKey:key]; 150 | } else if (image) { 151 | dispatch_async(YYImageCacheIOQueue(), ^{ 152 | __strong typeof(_self) self = _self; 153 | if (!self) return; 154 | NSData *data = [image yy_imageDataRepresentation]; 155 | [YYDiskCache setExtendedData:[NSKeyedArchiver archivedDataWithRootObject:@(image.scale)] toObject:data]; 156 | [self.diskCache setObject:data forKey:key]; 157 | }); 158 | } 159 | } 160 | } 161 | 162 | - (void)removeImageForKey:(NSString *)key { 163 | [self removeImageForKey:key withType:YYImageCacheTypeAll]; 164 | } 165 | 166 | - (void)removeImageForKey:(NSString *)key withType:(YYImageCacheType)type { 167 | if (type & YYImageCacheTypeMemory) [_memoryCache removeObjectForKey:key]; 168 | if (type & YYImageCacheTypeDisk) [_diskCache removeObjectForKey:key]; 169 | } 170 | 171 | - (BOOL)containsImageForKey:(NSString *)key { 172 | return [self containsImageForKey:key withType:YYImageCacheTypeAll]; 173 | } 174 | 175 | - (BOOL)containsImageForKey:(NSString *)key withType:(YYImageCacheType)type { 176 | if (type & YYImageCacheTypeMemory) { 177 | if ([_memoryCache containsObjectForKey:key]) return YES; 178 | } 179 | if (type & YYImageCacheTypeDisk) { 180 | if ([_diskCache containsObjectForKey:key]) return YES; 181 | } 182 | return NO; 183 | } 184 | 185 | - (UIImage *)getImageForKey:(NSString *)key { 186 | return [self getImageForKey:key withType:YYImageCacheTypeAll]; 187 | } 188 | 189 | - (UIImage *)getImageForKey:(NSString *)key withType:(YYImageCacheType)type { 190 | if (!key) return nil; 191 | if (type & YYImageCacheTypeMemory) { 192 | UIImage *image = [_memoryCache objectForKey:key]; 193 | if (image) return image; 194 | } 195 | if (type & YYImageCacheTypeDisk) { 196 | NSData *data = (id)[_diskCache objectForKey:key]; 197 | UIImage *image = [self imageFromData:data]; 198 | if (image && (type & YYImageCacheTypeMemory)) { 199 | [_memoryCache setObject:image forKey:key withCost:[self imageCost:image]]; 200 | } 201 | return image; 202 | } 203 | return nil; 204 | } 205 | 206 | - (void)getImageForKey:(NSString *)key withType:(YYImageCacheType)type withBlock:(void (^)(UIImage *image, YYImageCacheType type))block { 207 | if (!block) return; 208 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 209 | UIImage *image = nil; 210 | 211 | if (type & YYImageCacheTypeMemory) { 212 | image = [_memoryCache objectForKey:key]; 213 | if (image) { 214 | dispatch_async(dispatch_get_main_queue(), ^{ 215 | block(image, YYImageCacheTypeMemory); 216 | }); 217 | return; 218 | } 219 | } 220 | 221 | if (type & YYImageCacheTypeDisk) { 222 | NSData *data = (id)[_diskCache objectForKey:key]; 223 | image = [self imageFromData:data]; 224 | if (image) { 225 | [_memoryCache setObject:image forKey:key]; 226 | dispatch_async(dispatch_get_main_queue(), ^{ 227 | block(image, YYImageCacheTypeDisk); 228 | }); 229 | return; 230 | } 231 | } 232 | 233 | dispatch_async(dispatch_get_main_queue(), ^{ 234 | block(nil, YYImageCacheTypeNone); 235 | }); 236 | }); 237 | } 238 | 239 | - (NSData *)getImageDataForKey:(NSString *)key { 240 | return (id)[_diskCache objectForKey:key]; 241 | } 242 | 243 | - (void)getImageDataForKey:(NSString *)key withBlock:(void (^)(NSData *imageData))block { 244 | if (!block) return; 245 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 246 | NSData *data = (id)[_diskCache objectForKey:key]; 247 | dispatch_async(dispatch_get_main_queue(), ^{ 248 | block(data); 249 | }); 250 | }); 251 | } 252 | 253 | @end 254 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/YYWebImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYWebImage.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/23. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | FOUNDATION_EXPORT double YYWebImageVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char YYWebImageVersionString[]; 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #else 26 | #import "YYImageCache.h" 27 | #import "YYWebImageOperation.h" 28 | #import "YYWebImageManager.h" 29 | #import "UIImage+YYWebImage.h" 30 | #import "UIImageView+YYWebImage.h" 31 | #import "UIButton+YYWebImage.h" 32 | #import "CALayer+YYWebImage.h" 33 | #import "MKAnnotationView+YYWebImage.h" 34 | #endif 35 | 36 | #if __has_include() 37 | #import 38 | #elif __has_include() 39 | #import 40 | #import 41 | #import 42 | #import 43 | #import 44 | #else 45 | #import "YYImage.h" 46 | #import "YYFrameImage.h" 47 | #import "YYSpriteSheetImage.h" 48 | #import "YYImageCoder.h" 49 | #import "YYAnimatedImageView.h" 50 | #endif 51 | 52 | #if __has_include() 53 | #import 54 | #elif __has_include() 55 | #import 56 | #import 57 | #import 58 | #import 59 | #else 60 | #import "YYCache.h" 61 | #import "YYMemoryCache.h" 62 | #import "YYDiskCache.h" 63 | #import "YYKVStorage.h" 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/YYWebImageManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYWebImageManager.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/19. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | #import 16 | #else 17 | #import "YYImageCache.h" 18 | #endif 19 | 20 | @class YYWebImageOperation; 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | /// The options to control image operation. 25 | typedef NS_OPTIONS(NSUInteger, YYWebImageOptions) { 26 | 27 | /// Show network activity on status bar when download image. 28 | YYWebImageOptionShowNetworkActivity = 1 << 0, 29 | 30 | /// Display progressive/interlaced/baseline image during download (same as web browser). 31 | YYWebImageOptionProgressive = 1 << 1, 32 | 33 | /// Display blurred progressive JPEG or interlaced PNG image during download. 34 | /// This will ignore baseline image for better user experience. 35 | YYWebImageOptionProgressiveBlur = 1 << 2, 36 | 37 | /// Use NSURLCache instead of YYImageCache. 38 | YYWebImageOptionUseNSURLCache = 1 << 3, 39 | 40 | /// Allows untrusted SSL ceriticates. 41 | YYWebImageOptionAllowInvalidSSLCertificates = 1 << 4, 42 | 43 | /// Allows background task to download image when app is in background. 44 | YYWebImageOptionAllowBackgroundTask = 1 << 5, 45 | 46 | /// Handles cookies stored in NSHTTPCookieStore. 47 | YYWebImageOptionHandleCookies = 1 << 6, 48 | 49 | /// Load the image from remote and refresh the image cache. 50 | YYWebImageOptionRefreshImageCache = 1 << 7, 51 | 52 | /// Do not load image from/to disk cache. 53 | YYWebImageOptionIgnoreDiskCache = 1 << 8, 54 | 55 | /// Do not change the view's image before set a new URL to it. 56 | YYWebImageOptionIgnorePlaceHolder = 1 << 9, 57 | 58 | /// Ignore image decoding. 59 | /// This may used for image downloading without display. 60 | YYWebImageOptionIgnoreImageDecoding = 1 << 10, 61 | 62 | /// Ignore multi-frame image decoding. 63 | /// This will handle the GIF/APNG/WebP/ICO image as single frame image. 64 | YYWebImageOptionIgnoreAnimatedImage = 1 << 11, 65 | 66 | /// Set the image to view with a fade animation. 67 | /// This will add a "fade" animation on image view's layer for better user experience. 68 | YYWebImageOptionSetImageWithFadeAnimation = 1 << 12, 69 | 70 | /// Do not set the image to the view when image fetch complete. 71 | /// You may set the image manually. 72 | YYWebImageOptionAvoidSetImage = 1 << 13, 73 | 74 | /// This flag will add the URL to a blacklist (in memory) when the URL fail to be downloaded, 75 | /// so the library won't keep trying. 76 | YYWebImageOptionIgnoreFailedURL = 1 << 14, 77 | }; 78 | 79 | /// Indicated where the image came from. 80 | typedef NS_ENUM(NSUInteger, YYWebImageFromType) { 81 | 82 | /// No value. 83 | YYWebImageFromNone = 0, 84 | 85 | /// Fetched from memory cache immediately. 86 | /// If you called "setImageWithURL:..." and the image is already in memory, 87 | /// then you will get this value at the same call. 88 | YYWebImageFromMemoryCacheFast, 89 | 90 | /// Fetched from memory cache. 91 | YYWebImageFromMemoryCache, 92 | 93 | /// Fetched from disk cache. 94 | YYWebImageFromDiskCache, 95 | 96 | /// Fetched from remote (web or file path). 97 | YYWebImageFromRemote, 98 | }; 99 | 100 | /// Indicated image fetch complete stage. 101 | typedef NS_ENUM(NSInteger, YYWebImageStage) { 102 | 103 | /// Incomplete, progressive image. 104 | YYWebImageStageProgress = -1, 105 | 106 | /// Cancelled. 107 | YYWebImageStageCancelled = 0, 108 | 109 | /// Finished (succeed or failed). 110 | YYWebImageStageFinished = 1, 111 | }; 112 | 113 | 114 | /** 115 | The block invoked in remote image fetch progress. 116 | 117 | @param receivedSize Current received size in bytes. 118 | @param expectedSize Expected total size in bytes (-1 means unknown). 119 | */ 120 | typedef void(^YYWebImageProgressBlock)(NSInteger receivedSize, NSInteger expectedSize); 121 | 122 | /** 123 | The block invoked before remote image fetch finished to do additional image process. 124 | 125 | @discussion This block will be invoked before `YYWebImageCompletionBlock` to give 126 | you a chance to do additional image process (such as resize or crop). If there's 127 | no need to transform the image, just return the `image` parameter. 128 | 129 | @example You can clip the image, blur it and add rounded corners with these code: 130 | ^(UIImage *image, NSURL *url) { 131 | // Maybe you need to create an @autoreleasepool to limit memory cost. 132 | image = [image yy_imageByResizeToSize:CGSizeMake(100, 100) contentMode:UIViewContentModeScaleAspectFill]; 133 | image = [image yy_imageByBlurRadius:20 tintColor:nil tintMode:kCGBlendModeNormal saturation:1.2 maskImage:nil]; 134 | image = [image yy_imageByRoundCornerRadius:5]; 135 | return image; 136 | } 137 | 138 | @param image The image fetched from url. 139 | @param url The image url (remote or local file path). 140 | @return The transformed image. 141 | */ 142 | typedef UIImage * _Nullable (^YYWebImageTransformBlock)(UIImage *image, NSURL *url); 143 | 144 | /** 145 | The block invoked when image fetch finished or cancelled. 146 | 147 | @param image The image. 148 | @param url The image url (remote or local file path). 149 | @param from Where the image came from. 150 | @param error Error during image fetching. 151 | @param finished If the operation is cancelled, this value is NO, otherwise YES. 152 | */ 153 | typedef void (^YYWebImageCompletionBlock)(UIImage * _Nullable image, 154 | NSURL *url, 155 | YYWebImageFromType from, 156 | YYWebImageStage stage, 157 | NSError * _Nullable error); 158 | 159 | 160 | 161 | 162 | /** 163 | A manager to create and manage web image operation. 164 | */ 165 | @interface YYWebImageManager : NSObject 166 | 167 | /** 168 | Returns global YYWebImageManager instance. 169 | 170 | @return YYWebImageManager shared instance. 171 | */ 172 | + (instancetype)sharedManager; 173 | 174 | /** 175 | Creates a manager with an image cache and operation queue. 176 | 177 | @param cache Image cache used by manager (pass nil to avoid image cache). 178 | @param queue The operation queue on which image operations are scheduled and run 179 | (pass nil to make the new operation start immediately without queue). 180 | @return A new manager. 181 | */ 182 | - (instancetype)initWithCache:(nullable YYImageCache *)cache 183 | queue:(nullable NSOperationQueue *)queue NS_DESIGNATED_INITIALIZER; 184 | 185 | - (instancetype)init UNAVAILABLE_ATTRIBUTE; 186 | + (instancetype)new UNAVAILABLE_ATTRIBUTE; 187 | 188 | /** 189 | Creates and returns a new image operation, the operation will start immediately. 190 | 191 | @param url The image url (remote or local file path). 192 | @param options The options to control image operation. 193 | @param progress Progress block which will be invoked on background thread (pass nil to avoid). 194 | @param transform Transform block which will be invoked on background thread (pass nil to avoid). 195 | @param completion Completion block which will be invoked on background thread (pass nil to avoid). 196 | @return A new image operation. 197 | */ 198 | - (nullable YYWebImageOperation *)requestImageWithURL:(NSURL *)url 199 | options:(YYWebImageOptions)options 200 | progress:(nullable YYWebImageProgressBlock)progress 201 | transform:(nullable YYWebImageTransformBlock)transform 202 | completion:(nullable YYWebImageCompletionBlock)completion; 203 | 204 | /** 205 | The image cache used by image operation. 206 | You can set it to nil to avoid image cache. 207 | */ 208 | @property (nullable, nonatomic, strong) YYImageCache *cache; 209 | 210 | /** 211 | The operation queue on which image operations are scheduled and run. 212 | You can set it to nil to make the new operation start immediately without queue. 213 | 214 | You can use this queue to control maximum number of concurrent operations, to obtain 215 | the status of the current operations, or to cancel all operations in this manager. 216 | */ 217 | @property (nullable, nonatomic, strong) NSOperationQueue *queue; 218 | 219 | /** 220 | The shared transform block to process image. Default is nil. 221 | 222 | When called `requestImageWithURL:options:progress:transform:completion` and 223 | the `transform` is nil, this block will be used. 224 | */ 225 | @property (nullable, nonatomic, copy) YYWebImageTransformBlock sharedTransformBlock; 226 | 227 | /** 228 | The image request timeout interval in seconds. Default is 15. 229 | */ 230 | @property (nonatomic) NSTimeInterval timeout; 231 | 232 | /** 233 | The username used by NSURLCredential, default is nil. 234 | */ 235 | @property (nullable, nonatomic, copy) NSString *username; 236 | 237 | /** 238 | The password used by NSURLCredential, default is nil. 239 | */ 240 | @property (nullable, nonatomic, copy) NSString *password; 241 | 242 | /** 243 | The image HTTP request header. Default is "Accept:image/webp,image/\*;q=0.8". 244 | */ 245 | @property (nullable, nonatomic, copy) NSDictionary *headers; 246 | 247 | /** 248 | A block which will be invoked for each image HTTP request to do additional 249 | HTTP header process. Default is nil. 250 | 251 | Use this block to add or remove HTTP header field for a specified URL. 252 | */ 253 | @property (nullable, nonatomic, copy) NSDictionary *(^headersFilter)(NSURL *url, NSDictionary * _Nullable header); 254 | 255 | /** 256 | A block which will be invoked for each image operation. Default is nil. 257 | 258 | Use this block to provide a custom image cache key for a specified URL. 259 | */ 260 | @property (nullable, nonatomic, copy) NSString *(^cacheKeyFilter)(NSURL *url); 261 | 262 | /** 263 | Returns the HTTP headers for a specified URL. 264 | 265 | @param url A specified URL. 266 | @return HTTP headers. 267 | */ 268 | - (nullable NSDictionary *)headersForURL:(NSURL *)url; 269 | 270 | /** 271 | Returns the cache key for a specified URL. 272 | 273 | @param url A specified URL 274 | @return Cache key used in YYImageCache. 275 | */ 276 | - (NSString *)cacheKeyForURL:(NSURL *)url; 277 | 278 | 279 | /** 280 | Increments the number of active network requests. 281 | If this number was zero before incrementing, this will start animating the 282 | status bar network activity indicator. 283 | 284 | This method is thread safe. 285 | 286 | This method has no effect in App Extension. 287 | */ 288 | + (void)incrementNetworkActivityCount; 289 | 290 | /** 291 | Decrements the number of active network requests. 292 | If this number becomes zero after decrementing, this will stop animating the 293 | status bar network activity indicator. 294 | 295 | This method is thread safe. 296 | 297 | This method has no effect in App Extension. 298 | */ 299 | + (void)decrementNetworkActivityCount; 300 | 301 | /** 302 | Get current number of active network requests. 303 | 304 | This method is thread safe. 305 | 306 | This method has no effect in App Extension. 307 | */ 308 | + (NSInteger)currentNetworkActivityCount; 309 | 310 | @end 311 | 312 | NS_ASSUME_NONNULL_END 313 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/YYWebImageManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // YYWebImageManager.m 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/19. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "YYWebImageManager.h" 13 | #import "YYImageCache.h" 14 | #import "YYWebImageOperation.h" 15 | #import "YYImageCoder.h" 16 | #import 17 | 18 | #define kNetworkIndicatorDelay (1/30.0) 19 | 20 | 21 | /// Returns nil in App Extension. 22 | static UIApplication *_YYSharedApplication() { 23 | static BOOL isAppExtension = NO; 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | Class cls = NSClassFromString(@"UIApplication"); 27 | if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES; 28 | if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES; 29 | }); 30 | #pragma clang diagnostic push 31 | #pragma clang diagnostic ignored "-Wundeclared-selector" 32 | return isAppExtension ? nil : [UIApplication performSelector:@selector(sharedApplication)]; 33 | #pragma clang diagnostic pop 34 | } 35 | 36 | 37 | @interface _YYWebImageApplicationNetworkIndicatorInfo : NSObject 38 | @property (nonatomic, assign) NSInteger count; 39 | @property (nonatomic, strong) NSTimer *timer; 40 | @end 41 | @implementation _YYWebImageApplicationNetworkIndicatorInfo 42 | @end 43 | 44 | @implementation YYWebImageManager 45 | 46 | + (instancetype)sharedManager { 47 | static YYWebImageManager *manager; 48 | static dispatch_once_t onceToken; 49 | dispatch_once(&onceToken, ^{ 50 | YYImageCache *cache = [YYImageCache sharedCache]; 51 | NSOperationQueue *queue = [NSOperationQueue new]; 52 | if ([queue respondsToSelector:@selector(setQualityOfService:)]) { 53 | queue.qualityOfService = NSQualityOfServiceBackground; 54 | } 55 | manager = [[self alloc] initWithCache:cache queue:queue]; 56 | }); 57 | return manager; 58 | } 59 | 60 | - (instancetype)init { 61 | @throw [NSException exceptionWithName:@"YYWebImageManager init error" reason:@"Use the designated initializer to init." userInfo:nil]; 62 | return [self initWithCache:nil queue:nil]; 63 | } 64 | 65 | - (instancetype)initWithCache:(YYImageCache *)cache queue:(NSOperationQueue *)queue{ 66 | self = [super init]; 67 | if (!self) return nil; 68 | _cache = cache; 69 | _queue = queue; 70 | _timeout = 15.0; 71 | if (YYImageWebPAvailable()) { 72 | _headers = @{ @"Accept" : @"image/webp,image/*;q=0.8" }; 73 | } else { 74 | _headers = @{ @"Accept" : @"image/*;q=0.8" }; 75 | } 76 | return self; 77 | } 78 | 79 | - (YYWebImageOperation *)requestImageWithURL:(NSURL *)url 80 | options:(YYWebImageOptions)options 81 | progress:(YYWebImageProgressBlock)progress 82 | transform:(YYWebImageTransformBlock)transform 83 | completion:(YYWebImageCompletionBlock)completion { 84 | 85 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 86 | request.timeoutInterval = _timeout; 87 | request.HTTPShouldHandleCookies = (options & YYWebImageOptionHandleCookies) != 0; 88 | request.allHTTPHeaderFields = [self headersForURL:url]; 89 | request.HTTPShouldUsePipelining = YES; 90 | request.cachePolicy = (options & YYWebImageOptionUseNSURLCache) ? 91 | NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData; 92 | 93 | YYWebImageOperation *operation = [[YYWebImageOperation alloc] initWithRequest:request 94 | options:options 95 | cache:_cache 96 | cacheKey:[self cacheKeyForURL:url] 97 | progress:progress 98 | transform:transform ? transform : _sharedTransformBlock 99 | completion:completion]; 100 | 101 | if (_username && _password) { 102 | operation.credential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceForSession]; 103 | } 104 | if (operation) { 105 | NSOperationQueue *queue = _queue; 106 | if (queue) { 107 | [queue addOperation:operation]; 108 | } else { 109 | [operation start]; 110 | } 111 | } 112 | return operation; 113 | } 114 | 115 | - (NSDictionary *)headersForURL:(NSURL *)url { 116 | if (!url) return nil; 117 | return _headersFilter ? _headersFilter(url, _headers) : _headers; 118 | } 119 | 120 | - (NSString *)cacheKeyForURL:(NSURL *)url { 121 | if (!url) return nil; 122 | return _cacheKeyFilter ? _cacheKeyFilter(url) : url.absoluteString; 123 | } 124 | 125 | 126 | 127 | #pragma mark Network Indicator 128 | 129 | + (_YYWebImageApplicationNetworkIndicatorInfo *)_networkIndicatorInfo { 130 | return objc_getAssociatedObject(self, @selector(_networkIndicatorInfo)); 131 | } 132 | 133 | + (void)_setNetworkIndicatorInfo:(_YYWebImageApplicationNetworkIndicatorInfo *)info { 134 | objc_setAssociatedObject(self, @selector(_networkIndicatorInfo), info, OBJC_ASSOCIATION_RETAIN); 135 | } 136 | 137 | + (void)_delaySetActivity:(NSTimer *)timer { 138 | UIApplication *app = _YYSharedApplication(); 139 | if (!app) return; 140 | 141 | NSNumber *visiable = timer.userInfo; 142 | if (app.networkActivityIndicatorVisible != visiable.boolValue) { 143 | [app setNetworkActivityIndicatorVisible:visiable.boolValue]; 144 | } 145 | [timer invalidate]; 146 | } 147 | 148 | + (void)_changeNetworkActivityCount:(NSInteger)delta { 149 | if (!_YYSharedApplication()) return; 150 | 151 | void (^block)() = ^{ 152 | _YYWebImageApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo]; 153 | if (!info) { 154 | info = [_YYWebImageApplicationNetworkIndicatorInfo new]; 155 | [self _setNetworkIndicatorInfo:info]; 156 | } 157 | NSInteger count = info.count; 158 | count += delta; 159 | info.count = count; 160 | [info.timer invalidate]; 161 | info.timer = [NSTimer timerWithTimeInterval:kNetworkIndicatorDelay target:self selector:@selector(_delaySetActivity:) userInfo:@(info.count > 0) repeats:NO]; 162 | [[NSRunLoop mainRunLoop] addTimer:info.timer forMode:NSRunLoopCommonModes]; 163 | }; 164 | if ([NSThread isMainThread]) { 165 | block(); 166 | } else { 167 | dispatch_async(dispatch_get_main_queue(), block); 168 | } 169 | } 170 | 171 | + (void)incrementNetworkActivityCount { 172 | [self _changeNetworkActivityCount:1]; 173 | } 174 | 175 | + (void)decrementNetworkActivityCount { 176 | [self _changeNetworkActivityCount:-1]; 177 | } 178 | 179 | + (NSInteger)currentNetworkActivityCount { 180 | _YYWebImageApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo]; 181 | return info.count; 182 | } 183 | 184 | @end 185 | -------------------------------------------------------------------------------- /HYNavigation/Vendors/YYWebImage/YYWebImageOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYWebImageOperation.h 3 | // YYWebImage 4 | // 5 | // Created by ibireme on 15/2/15. 6 | // Copyright (c) 2015 ibireme. 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | #if __has_include() 15 | #import 16 | #import 17 | #else 18 | #import "YYImageCache.h" 19 | #import "YYWebImageManager.h" 20 | #endif 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | /** 25 | The YYWebImageOperation class is an NSOperation subclass used to fetch image 26 | from URL request. 27 | 28 | @discussion It's an asynchronous operation. You typically execute it by adding 29 | it to an operation queue, or calls 'start' to execute it manually. When the 30 | operation is started, it will: 31 | 32 | 1. Get the image from the cache, if exist, return it with `completion` block. 33 | 2. Start an URL connection to fetch image from the request, invoke the `progress` 34 | to notify request progress (and invoke `completion` block to return the 35 | progressive image if enabled by progressive option). 36 | 3. Process the image by invoke the `transform` block. 37 | 4. Put the image to cache and return it with `completion` block. 38 | 39 | */ 40 | @interface YYWebImageOperation : NSOperation 41 | 42 | @property (nonatomic, strong, readonly) NSURLRequest *request; ///< The image URL request. 43 | @property (nullable, nonatomic, strong, readonly) NSURLResponse *response; ///< The response for request. 44 | @property (nullable, nonatomic, strong, readonly) YYImageCache *cache; ///< The image cache. 45 | @property (nonatomic, strong, readonly) NSString *cacheKey; ///< The image cache key. 46 | @property (nonatomic, readonly) YYWebImageOptions options; ///< The operation's option. 47 | 48 | /** 49 | Whether the URL connection should consult the credential storage for authenticating 50 | the connection. Default is YES. 51 | 52 | @discussion This is the value that is returned in the `NSURLConnectionDelegate` 53 | method `-connectionShouldUseCredentialStorage:`. 54 | */ 55 | @property (nonatomic) BOOL shouldUseCredentialStorage; 56 | 57 | /** 58 | The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. 59 | 60 | @discussion This will be overridden by any shared credentials that exist for the 61 | username or password of the request URL, if present. 62 | */ 63 | @property (nullable, nonatomic, strong) NSURLCredential *credential; 64 | 65 | /** 66 | Creates and returns a new operation. 67 | 68 | You should call `start` to execute this operation, or you can add the operation 69 | to an operation queue. 70 | 71 | @param request The Image request. This value should not be nil. 72 | @param options A mask to specify options to use for this operation. 73 | @param cache An image cache. Pass nil to avoid image cache. 74 | @param cacheKey An image cache key. Pass nil to avoid image cache. 75 | @param progress A block invoked in image fetch progress. 76 | The block will be invoked in background thread. Pass nil to avoid it. 77 | @param transform A block invoked before image fetch finished to do additional image process. 78 | The block will be invoked in background thread. Pass nil to avoid it. 79 | @param completion A block invoked when image fetch finished or cancelled. 80 | The block will be invoked in background thread. Pass nil to avoid it. 81 | 82 | @return The image request opeartion, or nil if an error occurs. 83 | */ 84 | - (instancetype)initWithRequest:(NSURLRequest *)request 85 | options:(YYWebImageOptions)options 86 | cache:(nullable YYImageCache *)cache 87 | cacheKey:(nullable NSString *)cacheKey 88 | progress:(nullable YYWebImageProgressBlock)progress 89 | transform:(nullable YYWebImageTransformBlock)transform 90 | completion:(nullable YYWebImageCompletionBlock)completion NS_DESIGNATED_INITIALIZER; 91 | 92 | - (instancetype)init UNAVAILABLE_ATTRIBUTE; 93 | + (instancetype)new UNAVAILABLE_ATTRIBUTE; 94 | 95 | @end 96 | 97 | NS_ASSUME_NONNULL_END 98 | -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/FirstViewViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewViewController.h 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/27. 6 | // Copyright © 2016年 Pengcent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FirstViewViewController : UIViewController 12 | 13 | @property (nonatomic, strong) id parameter; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/FirstViewViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewViewController.m 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/27. 6 | // Copyright © 2016年 Pengcent. All rights reserved. 7 | // 8 | #define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) 9 | 10 | #define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height) 11 | 12 | #import "FirstViewViewController.h" 13 | 14 | @interface FirstViewViewController () 15 | 16 | @end 17 | 18 | @implementation FirstViewViewController 19 | 20 | - (UIViewController *)getPresentedViewController 21 | { 22 | UIViewController *appRootVC = [UIApplication sharedApplication].keyWindow.rootViewController; 23 | UIViewController *topVC = appRootVC; 24 | if (topVC.presentedViewController) { 25 | topVC = topVC.presentedViewController; 26 | } 27 | return topVC; 28 | } 29 | 30 | - (void)viewDidLoad { 31 | UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; 32 | button.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.width); 33 | [button addTarget:self action:@selector(dismisVC:) forControlEvents:UIControlEventTouchUpInside]; 34 | button.backgroundColor = [UIColor cyanColor]; 35 | [button setTitle:@"disappear😛" forState:UIControlStateNormal]; 36 | [self.view addSubview:button]; 37 | 38 | [super viewDidLoad]; 39 | } 40 | - (void)dismisVC:(UIButton *)button{ 41 | [[self getPresentedViewController] dismissViewControllerAnimated:YES completion:nil]; 42 | 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/26. 6 | // Copyright © 2016年 Pengcent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/26. 6 | // Copyright © 2016年 Pengcent. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "HYPageView.h" 11 | #import "WaterFlowCollectionViewController.h" 12 | 13 | #define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) 14 | 15 | #define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height) 16 | 17 | @interface ViewController (){ 18 | NSArray *_titles; 19 | } 20 | 21 | @property (nonatomic, strong) UITableView *tableView; 22 | 23 | @end 24 | 25 | @implementation ViewController 26 | 27 | - (void)createTableView{ 28 | _tableView = [[UITableView alloc] initWithFrame:self.view.bounds]; 29 | _tableView.delegate = self; 30 | _tableView.dataSource = self; 31 | [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; 32 | _tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); 33 | [self.view addSubview:_tableView]; 34 | 35 | _tableView.tableFooterView = [UIView new]; 36 | } 37 | 38 | - (void)viewDidLoad { 39 | [super viewDidLoad]; 40 | [self createTableView]; 41 | _titles = @[@"样例1.仿照优酷首页",@"样例2.仿照优酷Vip会员页面",@"样例3.仿照网易云音乐首页",@"样例4.瞎写",@"每页最后一页是返回"]; 42 | } 43 | 44 | 45 | - (HYPageView *)test0 { 46 | HYPageView *pageView = [[HYPageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) withTitles:@[@"头条",@"精选",@"新好声音"] withViewControllers:@[@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"FirstViewViewController"] withParameters:@[@"123",@"这是一片很寂寞的天"]]; 47 | 48 | UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeSystem]; 49 | [leftButton setImage:[UIImage imageNamed:@"search_"] forState:UIControlStateNormal]; 50 | leftButton.frame = CGRectMake(0, 0, 50, 40); 51 | [leftButton setTintColor:[UIColor blackColor]]; 52 | leftButton.transform = CGAffineTransformMakeScale(.7, .7); 53 | pageView.leftButton = leftButton; 54 | 55 | UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeSystem]; 56 | [rightButton setImage:[UIImage imageNamed:@"more_"] forState:UIControlStateNormal]; 57 | rightButton.frame = CGRectMake(0, 0, 50, 40); 58 | [rightButton setTintColor:[UIColor blackColor]]; 59 | rightButton.transform = CGAffineTransformMakeScale(.5, .5); 60 | pageView.rightButton = rightButton; 61 | pageView.defaultSubscript = 0; 62 | return pageView; 63 | } 64 | 65 | - (HYPageView *)test1 { 66 | 67 | WaterFlowCollectionViewController *vc = [WaterFlowCollectionViewController new]; 68 | 69 | HYPageView *pageView = [[HYPageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) withTitles:@[@"精选",@"片库",@"电影",@"韩剧",@"德云社",@"动漫",@"电视剧",@"纪录片"] withViewControllers:@[@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",vc,@"FirstViewViewController"] withParameters:nil]; 70 | pageView.pageViewStyle = HYPageViewStyleB; 71 | 72 | pageView.isTranslucent = NO; 73 | pageView.topTabViewColor = [UIColor colorWithRed:211/255. green:111/255. blue:39/255. alpha:.5]; 74 | pageView.selectedColor = [UIColor yellowColor]; 75 | 76 | UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeSystem]; 77 | [leftButton setImage:[UIImage imageNamed:@"search_"] forState:UIControlStateNormal]; 78 | pageView.isAdapteNavigationBar = NO; 79 | leftButton.frame = CGRectMake(0, 0, 50, 40); 80 | [leftButton setTintColor:[UIColor blackColor]]; 81 | leftButton.transform = CGAffineTransformMakeScale(.7, .7); 82 | pageView.leftButton = leftButton; 83 | pageView.defaultSubscript = 1; 84 | return pageView; 85 | } 86 | 87 | - (HYPageView *)test2 { 88 | HYPageView *pageView = [[HYPageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) withTitles:@[@"个性推介",@"歌单",@"主播电台",@"排行榜"] withViewControllers:@[@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"FirstViewViewController"] withParameters:nil]; 89 | pageView.pageViewStyle = HYPageViewStyleB; 90 | pageView.selectedColor = [UIColor redColor]; 91 | pageView.unselectedColor = [UIColor blackColor]; 92 | pageView.defaultSubscript = 2; 93 | 94 | return pageView; 95 | } 96 | 97 | - (HYPageView *)test3 { 98 | HYPageView *pageView = [[HYPageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) withTitles:@[@"One",@"Two",@"Three",@"Four",@"Five",@"Six"] withViewControllers:@[@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"FirstViewViewController"] withParameters:nil]; 99 | pageView.pageViewStyle = HYPageViewStyleB; 100 | pageView.selectedColor = [UIColor redColor]; 101 | pageView.unselectedColor = [UIColor blackColor]; 102 | pageView.font = [UIFont fontWithName:@"Zapfino" size:16]; 103 | pageView.defaultSubscript = 2; 104 | return pageView; 105 | } 106 | 107 | - (HYPageView *)test4 { 108 | 109 | HYPageView *pageView = [[HYPageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) withTitles:@[@"我实在",@"也",@"想不出",@"头上",@"写",@"点啥了"] withViewControllers:@[@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"WaterFlowCollectionViewController",@"FirstViewViewController"] withParameters:nil]; 110 | pageView.pageViewStyle = HYPageViewStyleB; 111 | 112 | pageView.isAnimated = YES; 113 | pageView.selectedColor = [UIColor blueColor]; 114 | pageView.unselectedColor = [UIColor blackColor]; 115 | pageView.font = [UIFont fontWithName:@"HoeflerText-Black" size:18]; 116 | pageView.defaultSubscript = 4; 117 | return pageView; 118 | } 119 | 120 | - (void)viewWillAppear:(BOOL)animated{ 121 | [super viewWillAppear:animated]; 122 | [self.navigationController setNavigationBarHidden:NO animated:NO]; 123 | } 124 | 125 | #pragma mark - DataSource & Delegate 126 | 127 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 128 | { 129 | return 1; 130 | } 131 | 132 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 133 | { 134 | return 5; 135 | } 136 | 137 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 138 | { 139 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; 140 | 141 | cell.textLabel.text = _titles[indexPath.row]; 142 | 143 | return cell; 144 | } 145 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 146 | return 80; 147 | } 148 | 149 | 150 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 151 | { 152 | switch (indexPath.row) { 153 | case 0: 154 | { 155 | UIViewController *v = [UIViewController new]; 156 | [self.navigationController setNavigationBarHidden:YES animated:NO]; 157 | [v.view addSubview:[self test0]]; 158 | [self showViewController:v sender:nil]; 159 | 160 | } 161 | break; 162 | case 1: 163 | { 164 | UIViewController *v = [UIViewController new]; 165 | [v.view addSubview:[self test1]]; 166 | [self showViewController:v sender:nil]; 167 | 168 | } 169 | break; 170 | case 2: 171 | { 172 | UIViewController *v = [UIViewController new]; 173 | UINavigationController *nv = [[UINavigationController alloc]initWithRootViewController:v]; 174 | [v.view addSubview:[self test2]]; 175 | [self showViewController:nv sender:nil]; 176 | } 177 | break; 178 | 179 | case 3: 180 | { 181 | UIViewController *v = [UIViewController new]; 182 | [v.view addSubview:[self test3]]; 183 | [self showViewController:v sender:nil]; 184 | } 185 | break; 186 | 187 | default: 188 | { 189 | UIViewController *v = [UIViewController new]; 190 | [v.view addSubview:[self test4]]; 191 | [self showViewController:v sender:nil]; 192 | } 193 | break; 194 | } 195 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 196 | } 197 | 198 | @end 199 | -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/WoterFlow/WaterFlowCollectionViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WaterFlowCollectionViewController.h 3 | // CollectionPictures 4 | // 5 | // Created by runlhy on 16/7/2. 6 | // Copyright © 2016年 runlhy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WaterFlowCollectionViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/WoterFlow/WaterFlowCollectionViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WaterFlowCollectionViewController.m 3 | // CollectionPictures 4 | // 5 | // Created by runlhy on 16/7/2. 6 | // Copyright © 2016年 runlhy. All rights reserved. 7 | // 8 | 9 | #import "WaterFlowCollectionViewController.h" 10 | #import "WaterFlowLayout.h" 11 | #import "YYWebImage.h" 12 | #import "WaterFlowCollectionViewCell.h" 13 | 14 | @interface WaterFlowCollectionViewController () 15 | { 16 | UICollectionView *_collectionView; 17 | } 18 | 19 | @property (nonatomic, strong) NSMutableArray *allDataArray; 20 | @property (nonatomic, strong) NSMutableArray *randomDataArray; 21 | 22 | @end 23 | 24 | @implementation WaterFlowCollectionViewController 25 | 26 | - (void)dealloc{ 27 | //NSLog(@"%@",self.class); 28 | } 29 | 30 | - (NSMutableArray *)randomDataArray 31 | { 32 | if (!_randomDataArray){ 33 | _randomDataArray = [NSMutableArray array]; 34 | } 35 | return _randomDataArray; 36 | } 37 | 38 | - (NSMutableArray *)allDataArray 39 | { 40 | if (!_allDataArray){ 41 | _allDataArray = [NSMutableArray array]; 42 | } 43 | return _allDataArray; 44 | } 45 | 46 | - (void)viewDidLoad { 47 | [super viewDidLoad]; 48 | 49 | WaterFlowLayout *waterFlowLayout = [WaterFlowLayout new]; 50 | 51 | _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:waterFlowLayout]; 52 | 53 | _collectionView.backgroundColor = [UIColor whiteColor]; 54 | _collectionView.delegate = self; 55 | _collectionView.dataSource = self; 56 | 57 | [_collectionView registerNib:[UINib nibWithNibName:@"WaterFlowCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"WaterFlowCollectionViewCell"]; 58 | self.view = _collectionView; 59 | // [self.view addSubview:_collectionView]; 60 | [self requestData]; 61 | 62 | } 63 | 64 | - (void)requestData{ 65 | NSString *path = [[NSBundle mainBundle] pathForResource:@"x" ofType:@"txt"]; 66 | NSString *string = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; 67 | NSArray *array = [string componentsSeparatedByString:@"\n"]; 68 | for (NSString *obj in array) { 69 | if ([obj containsString:@"http"] && [obj containsString:@"_240x426"] && ![obj containsString:@"_480x852"]) { 70 | [self.allDataArray addObject:obj]; 71 | } 72 | } 73 | 74 | for (NSInteger i=0; i<27; i++) { 75 | [self.randomDataArray addObject:self.allDataArray[arc4random() % self.allDataArray.count]]; 76 | } 77 | [_collectionView reloadData]; 78 | 79 | } 80 | 81 | #pragma mark - UICollectionView DataSource 82 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ 83 | return 1; 84 | } 85 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ 86 | return self.randomDataArray.count; 87 | } 88 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ 89 | WaterFlowCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"WaterFlowCollectionViewCell" forIndexPath:indexPath]; 90 | NSURL *url = [NSURL URLWithString:self.randomDataArray[indexPath.row]]; 91 | [cell.imgView yy_setImageWithURL:url options:YYWebImageOptionProgressive]; 92 | return cell; 93 | } 94 | 95 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ 96 | if (self.navigationController) { 97 | [self.navigationController pushViewController:[WaterFlowCollectionViewController new] animated:YES]; 98 | } 99 | 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/WoterFlow/WaterFlowLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // WaterFlowLayout.h 3 | // UICollectionDemo_01 4 | // 5 | // Created by runlhy on 16/6/16. 6 | // Copyright © 2016年 runlhy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WaterFlowLayout : UICollectionViewLayout 12 | 13 | @end -------------------------------------------------------------------------------- /HYNavigation/ViewControllers/WoterFlow/WaterFlowLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // WaterFlowLayout.m 3 | // UICollectionDemo_01 4 | // 5 | // Created by runlhy on 16/6/16. 6 | // Copyright © 2016年 runlhy. All rights reserved. 7 | // 8 | 9 | #import "WaterFlowLayout.h" 10 | 11 | static const CGFloat defaultColumnMargin = 3; 12 | static const CGFloat defaultRowMargin = 3; 13 | static const UIEdgeInsets defaultEdgeInsets = {3, 3, 3, 3}; 14 | static const NSInteger defaultColumnCount = 3; 15 | static const NSInteger defaultHeight = 100; 16 | 17 | @interface WaterFlowLayout () 18 | 19 | /** 存放所有cell的布局属性 */ 20 | @property (nonatomic, strong) NSMutableArray *attrsArray; 21 | 22 | /** collection滚动高度 */ 23 | @property (nonatomic, assign) CGFloat maxHeight; 24 | 25 | /** 当前高度 */ 26 | @property (nonatomic, assign) CGFloat sectionHeight; 27 | 28 | /** 当前最大y */ 29 | @property (nonatomic, assign) CGFloat maxSectionHeight; 30 | 31 | @end 32 | 33 | @implementation WaterFlowLayout 34 | 35 | #pragma mark - lazy 36 | - (NSMutableArray *)attrsArray 37 | { 38 | if (!_attrsArray){ 39 | _attrsArray = [NSMutableArray array]; 40 | } 41 | return _attrsArray; 42 | } 43 | 44 | /** 45 | * 初始化 46 | */ 47 | - (void)prepareLayout{ 48 | [super prepareLayout]; 49 | 50 | // 清除之前所有的布局属性 51 | [self.attrsArray removeAllObjects]; 52 | self.attrsArray = nil; 53 | 54 | //创建cell对应的布局属性 55 | for (int j=0; j<[self.collectionView numberOfSections]; j++) { 56 | NSInteger count = [self.collectionView numberOfItemsInSection:j]; 57 | for (NSInteger i = 0; i < count; i++) { 58 | //创建位置 59 | NSIndexPath *indexpath = [NSIndexPath indexPathForItem:i inSection:j]; 60 | //获取indexPath对应的布局属性 61 | UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexpath]; 62 | 63 | [self.attrsArray addObject:attrs]; 64 | } 65 | } 66 | } 67 | /** 68 | * 决定cell的排布 69 | */ 70 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ 71 | //NSLog(@"%s",__func__); 72 | return self.attrsArray; 73 | } 74 | /** 75 | * 返回indexpath对应cell的 布局的属性 76 | */ 77 | - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ 78 | 79 | //创建布局属性 80 | UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 81 | 82 | // collectionView的宽度 83 | CGFloat collectionViewW = self.collectionView.frame.size.width; 84 | CGFloat w = (collectionViewW - defaultEdgeInsets.left - defaultEdgeInsets.right - (defaultColumnCount - 1)*defaultColumnMargin)/defaultColumnCount; 85 | CGFloat h = w / ((sqrt(5.0)-1)/2.0); 86 | CGFloat x = defaultEdgeInsets.left; 87 | CGFloat y = defaultEdgeInsets.top; 88 | 89 | //12个为一个周期 根据周期计算位置 90 | NSInteger section = indexPath.row / 6; 91 | NSInteger row = indexPath.row % 6; 92 | switch (row) { 93 | case 0: 94 | case 1: 95 | case 2:{ 96 | y = section * (3 * (h + defaultRowMargin)) + defaultEdgeInsets.top; 97 | x = defaultEdgeInsets.left + row * (w + defaultColumnMargin); 98 | } 99 | break; 100 | case 3:{ 101 | if (section % 2 == 0){ 102 | y = (3 * section + 1) * (h + defaultRowMargin) + defaultEdgeInsets.top; 103 | }else{ 104 | y = (3 * section + 1) * (h + defaultRowMargin) + defaultEdgeInsets.top; 105 | w = w * 2 + defaultColumnMargin; 106 | h = h * 2 + defaultRowMargin; 107 | } 108 | } 109 | break; 110 | case 4:{ 111 | if (section % 2 == 0){ 112 | y = (3 * section + 2) * (h + defaultRowMargin) + defaultEdgeInsets.top; 113 | }else{ 114 | x = defaultEdgeInsets.left + 2 * (w + defaultColumnMargin); 115 | y = (3 * section + 1) * (h + defaultRowMargin) + defaultEdgeInsets.top; 116 | } 117 | } 118 | break; 119 | default:{ 120 | if (section % 2 == 0){ 121 | x = defaultEdgeInsets.left + w + defaultColumnMargin; 122 | y = (3 * section + 1) * (h + defaultRowMargin) + defaultEdgeInsets.top; 123 | w = w * 2 + defaultColumnMargin; 124 | h = h * 2 + defaultRowMargin; 125 | }else{ 126 | x = defaultEdgeInsets.left + 2 * (w + defaultColumnMargin); 127 | y = (3 * section + 2) * (h + defaultRowMargin) + defaultEdgeInsets.top; 128 | } 129 | } 130 | break; 131 | } 132 | 133 | //设置布局属性的frame 134 | y += _sectionHeight; 135 | attributes.frame = CGRectMake(x, y, w, h); 136 | 137 | //解决最后一块小于前一块的问题 138 | if (_maxSectionHeight < y + h) { 139 | _maxSectionHeight = y + h; 140 | } 141 | //下一组时 更新高度 142 | if (indexPath.row == [self.collectionView numberOfItemsInSection:indexPath.section]-1) { 143 | _sectionHeight = _maxSectionHeight + defaultEdgeInsets.bottom; 144 | } 145 | //获得最底部位置 146 | _maxHeight = _maxSectionHeight + defaultEdgeInsets.bottom; 147 | return attributes; 148 | } 149 | 150 | /** 151 | * 滚动范围 152 | */ 153 | - (CGSize)collectionViewContentSize{ 154 | return CGSizeMake(0,_maxHeight); 155 | } 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /HYNavigation/Views/WaterFlowCollectionViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // WaterFlowCollectionViewCell.h 3 | // CollectionPictures 4 | // 5 | // Created by runlhy on 16/7/2. 6 | // Copyright © 2016年 runlhy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WaterFlowCollectionViewCell : UICollectionViewCell 12 | @property (weak, nonatomic) IBOutlet UIImageView *imgView; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /HYNavigation/Views/WaterFlowCollectionViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // WaterFlowCollectionViewCell.m 3 | // CollectionPictures 4 | // 5 | // Created by runlhy on 16/7/2. 6 | // Copyright © 2016年 runlhy. All rights reserved. 7 | // 8 | 9 | #import "WaterFlowCollectionViewCell.h" 10 | 11 | @implementation WaterFlowCollectionViewCell 12 | 13 | - (void)awakeFromNib { 14 | // Initialization code 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /HYNavigation/Views/WaterFlowCollectionViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /HYNavigation/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HYNavigation 4 | // 5 | // Created by runlhy on 16/9/26. 6 | // Copyright © 2016年 Pengcent. 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 | # HYPageView 2 | ## 类似优酷,网易云音乐导航条,代码足够简单,使用足够简单。 3 | 4 | 5 | ![HYPageView05.gif](http://upload-images.jianshu.io/upload_images/1155795-5a42faa4b377b337.gif?imageMogr2/auto-orient/strip) 6 | 7 | 8 | 9 | ![HYPageView08.gif](http://upload-images.jianshu.io/upload_images/1155795-e905d58548e59b82.gif?imageMogr2/auto-orient/strip) 10 | 11 | 12 | 13 | ![HYPageView06.gif](http://upload-images.jianshu.io/upload_images/1155795-217300c36772e630.gif?imageMogr2/auto-orient/strip) 14 | 15 | 16 | 17 | ![HYPageView03.gif](http://upload-images.jianshu.io/upload_images/1155795-359466ab92244108.gif?imageMogr2/auto-orient/strip) 18 | 19 | 20 | --------------------------------------------------------------------------------