一折买app------返利---------返利宝

MarqueeLabel.m 66KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776
  1. //
  2. // MarqueeLabel.m
  3. //
  4. // Created by Charles Powell on 1/31/11.
  5. // Copyright (c) 2011-2015 Charles Powell. All rights reserved.
  6. //
  7. #import "MarqueeLabel.h"
  8. #import <QuartzCore/QuartzCore.h>
  9. // Notification strings
  10. NSString *const kMarqueeLabelControllerRestartNotification = @"MarqueeLabelViewControllerRestart";
  11. NSString *const kMarqueeLabelShouldLabelizeNotification = @"MarqueeLabelShouldLabelizeNotification";
  12. NSString *const kMarqueeLabelShouldAnimateNotification = @"MarqueeLabelShouldAnimateNotification";
  13. NSString *const kMarqueeLabelAnimationCompletionBlock = @"MarqueeLabelAnimationCompletionBlock";
  14. // Animation completion block
  15. typedef void(^MLAnimationCompletionBlock)(BOOL finished);
  16. // iOS Version check for iOS 8.0.0
  17. #define SYSTEM_VERSION_IS_8_0_X ([[[UIDevice currentDevice] systemVersion] hasPrefix:@"8.0"])
  18. // Define "a long time" for MLLeft and MLRight types
  19. #define CGFLOAT_LONG_DURATION 60*60*24*365 // One year in seconds
  20. // Helpers
  21. @interface GradientSetupAnimation : CABasicAnimation
  22. @end
  23. @interface UIView (MarqueeLabelHelpers)
  24. - (UIViewController *)firstAvailableViewController;
  25. - (id)traverseResponderChainForFirstViewController;
  26. @end
  27. @interface CAMediaTimingFunction (MarqueeLabelHelpers)
  28. - (NSArray *)controlPoints;
  29. - (CGFloat)durationPercentageForPositionPercentage:(CGFloat)positionPercentage withDuration:(NSTimeInterval)duration;
  30. @end
  31. @interface MarqueeLabel()
  32. @property (nonatomic, strong) UILabel *subLabel;
  33. @property (nonatomic, assign) NSTimeInterval animationDuration;
  34. @property (nonatomic, assign, readonly) BOOL labelShouldScroll;
  35. @property (nonatomic, weak) UITapGestureRecognizer *tapRecognizer;
  36. @property (nonatomic, assign) CGRect homeLabelFrame;
  37. @property (nonatomic, assign) CGFloat awayOffset;
  38. @property (nonatomic, assign, readwrite) BOOL isPaused;
  39. // Support
  40. @property (nonatomic, copy) MLAnimationCompletionBlock scrollCompletionBlock;
  41. @property (nonatomic, strong) NSArray *gradientColors;
  42. CGPoint MLOffsetCGPoint(CGPoint point, CGFloat offset);
  43. @end
  44. @implementation MarqueeLabel
  45. #pragma mark - Class Methods and handlers
  46. + (void)restartLabelsOfController:(UIViewController *)controller {
  47. [MarqueeLabel notifyController:controller
  48. withMessage:kMarqueeLabelControllerRestartNotification];
  49. }
  50. + (void)controllerViewWillAppear:(UIViewController *)controller {
  51. [MarqueeLabel restartLabelsOfController:controller];
  52. }
  53. + (void)controllerViewDidAppear:(UIViewController *)controller {
  54. [MarqueeLabel restartLabelsOfController:controller];
  55. }
  56. + (void)controllerViewAppearing:(UIViewController *)controller {
  57. [MarqueeLabel restartLabelsOfController:controller];
  58. }
  59. + (void)controllerLabelsShouldLabelize:(UIViewController *)controller {
  60. [MarqueeLabel notifyController:controller
  61. withMessage:kMarqueeLabelShouldLabelizeNotification];
  62. }
  63. + (void)controllerLabelsShouldAnimate:(UIViewController *)controller {
  64. [MarqueeLabel notifyController:controller
  65. withMessage:kMarqueeLabelShouldAnimateNotification];
  66. }
  67. + (void)notifyController:(UIViewController *)controller withMessage:(NSString *)message
  68. {
  69. if (controller && message) {
  70. [[NSNotificationCenter defaultCenter] postNotificationName:message
  71. object:nil
  72. userInfo:[NSDictionary dictionaryWithObject:controller
  73. forKey:@"controller"]];
  74. }
  75. }
  76. - (void)viewControllerShouldRestart:(NSNotification *)notification {
  77. UIViewController *controller = [[notification userInfo] objectForKey:@"controller"];
  78. if (controller == [self firstAvailableViewController]) {
  79. [self restartLabel];
  80. }
  81. }
  82. - (void)labelsShouldLabelize:(NSNotification *)notification {
  83. UIViewController *controller = [[notification userInfo] objectForKey:@"controller"];
  84. if (controller == [self firstAvailableViewController]) {
  85. self.labelize = YES;
  86. }
  87. }
  88. - (void)labelsShouldAnimate:(NSNotification *)notification {
  89. UIViewController *controller = [[notification userInfo] objectForKey:@"controller"];
  90. if (controller == [self firstAvailableViewController]) {
  91. self.labelize = NO;
  92. }
  93. }
  94. #pragma mark - Initialization and Label Config
  95. - (id)initWithFrame:(CGRect)frame {
  96. return [self initWithFrame:frame duration:7.0 andFadeLength:0.0];
  97. }
  98. - (id)initWithFrame:(CGRect)frame duration:(NSTimeInterval)aLengthOfScroll andFadeLength:(CGFloat)aFadeLength {
  99. self = [super initWithFrame:frame];
  100. if (self) {
  101. [self setupLabel];
  102. _scrollDuration = aLengthOfScroll;
  103. self.fadeLength = MIN(aFadeLength, frame.size.width/2);
  104. }
  105. return self;
  106. }
  107. - (id)initWithFrame:(CGRect)frame rate:(CGFloat)pixelsPerSec andFadeLength:(CGFloat)aFadeLength {
  108. self = [super initWithFrame:frame];
  109. if (self) {
  110. [self setupLabel];
  111. _rate = pixelsPerSec;
  112. self.fadeLength = MIN(aFadeLength, frame.size.width/2);
  113. }
  114. return self;
  115. }
  116. - (id)initWithCoder:(NSCoder *)aDecoder {
  117. self = [super initWithCoder:aDecoder];
  118. if (self) {
  119. [self setupLabel];
  120. if (self.scrollDuration == 0) {
  121. self.scrollDuration = 7.0;
  122. }
  123. }
  124. return self;
  125. }
  126. - (void)awakeFromNib {
  127. [super awakeFromNib];
  128. [self forwardPropertiesToSubLabel];
  129. }
  130. - (void)prepareForInterfaceBuilder {
  131. [super prepareForInterfaceBuilder];
  132. [self forwardPropertiesToSubLabel];
  133. }
  134. + (Class)layerClass {
  135. return [CAReplicatorLayer class];
  136. }
  137. - (CAReplicatorLayer *)repliLayer {
  138. return (CAReplicatorLayer *)self.layer;
  139. }
  140. - (CAGradientLayer *)maskLayer {
  141. return (CAGradientLayer *)self.layer.mask;
  142. }
  143. - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
  144. // Do NOT call super, to prevent UILabel superclass from drawing into context
  145. // Label drawing is handled by sublabel and CAReplicatorLayer layer class
  146. // Draw only background color
  147. CGContextSetFillColorWithColor(ctx, self.backgroundColor.CGColor);
  148. CGContextFillRect(ctx, layer.bounds);
  149. }
  150. - (void)forwardPropertiesToSubLabel {
  151. /*
  152. Note that this method is currently ONLY called from awakeFromNib, i.e. when
  153. text properties are set via a Storyboard. As the Storyboard/IB doesn't currently
  154. support attributed strings, there's no need to "forward" the super attributedString value.
  155. */
  156. // Since we're a UILabel, we actually do implement all of UILabel's properties.
  157. // We don't care about these values, we just want to forward them on to our sublabel.
  158. NSArray *properties = @[@"baselineAdjustment", @"enabled", @"highlighted", @"highlightedTextColor",
  159. @"minimumFontSize", @"textAlignment",
  160. @"userInteractionEnabled", @"adjustsFontSizeToFitWidth",
  161. @"lineBreakMode", @"numberOfLines", @"contentMode"];
  162. // Iterate through properties
  163. self.subLabel.text = super.text;
  164. self.subLabel.font = super.font;
  165. self.subLabel.textColor = super.textColor;
  166. self.subLabel.backgroundColor = (super.backgroundColor == nil ? [UIColor clearColor] : super.backgroundColor);
  167. self.subLabel.shadowColor = super.shadowColor;
  168. self.subLabel.shadowOffset = super.shadowOffset;
  169. for (NSString *property in properties) {
  170. id val = [super valueForKey:property];
  171. [self.subLabel setValue:val forKey:property];
  172. }
  173. }
  174. - (void)setupLabel {
  175. // Basic UILabel options override
  176. self.clipsToBounds = YES;
  177. self.numberOfLines = 1;
  178. // Create first sublabel
  179. self.subLabel = [[UILabel alloc] initWithFrame:self.bounds];
  180. self.subLabel.tag = 700;
  181. self.subLabel.layer.anchorPoint = CGPointMake(0.0f, 0.0f);
  182. [self addSubview:self.subLabel];
  183. // Setup default values
  184. _marqueeType = MLContinuous;
  185. _awayOffset = 0.0f;
  186. _animationCurve = UIViewAnimationOptionCurveLinear;
  187. _labelize = NO;
  188. _holdScrolling = NO;
  189. _tapToScroll = NO;
  190. _isPaused = NO;
  191. _fadeLength = 0.0f;
  192. _animationDelay = 1.0;
  193. _animationDuration = 0.0f;
  194. _leadingBuffer = 0.0f;
  195. _trailingBuffer = 0.0f;
  196. // Add notification observers
  197. // Custom class notifications
  198. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewControllerShouldRestart:) name:kMarqueeLabelControllerRestartNotification object:nil];
  199. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(labelsShouldLabelize:) name:kMarqueeLabelShouldLabelizeNotification object:nil];
  200. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(labelsShouldAnimate:) name:kMarqueeLabelShouldAnimateNotification object:nil];
  201. // UIApplication state notifications
  202. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restartLabel) name:UIApplicationDidBecomeActiveNotification object:nil];
  203. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdownLabel) name:UIApplicationDidEnterBackgroundNotification object:nil];
  204. }
  205. - (void)minimizeLabelFrameWithMaximumSize:(CGSize)maxSize adjustHeight:(BOOL)adjustHeight {
  206. if (self.subLabel.text != nil) {
  207. // Calculate text size
  208. if (CGSizeEqualToSize(maxSize, CGSizeZero)) {
  209. maxSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
  210. }
  211. CGSize minimumLabelSize = [self subLabelSize];
  212. // Adjust for fade length
  213. CGSize minimumSize = CGSizeMake(minimumLabelSize.width + (self.fadeLength * 2), minimumLabelSize.height);
  214. // Find minimum size of options
  215. minimumSize = CGSizeMake(MIN(minimumSize.width, maxSize.width), MIN(minimumSize.height, maxSize.height));
  216. // Apply to frame
  217. self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, minimumSize.width, (adjustHeight ? minimumSize.height : self.frame.size.height));
  218. }
  219. }
  220. -(void)didMoveToSuperview {
  221. [self updateSublabel];
  222. }
  223. #pragma mark - MarqueeLabel Heavy Lifting
  224. - (void)layoutSubviews
  225. {
  226. [super layoutSubviews];
  227. [self updateSublabel];
  228. }
  229. - (void)willMoveToWindow:(UIWindow *)newWindow {
  230. if (!newWindow) {
  231. [self shutdownLabel];
  232. }
  233. }
  234. - (void)didMoveToWindow {
  235. if (!self.window) {
  236. [self shutdownLabel];
  237. } else {
  238. [self updateSublabel];
  239. }
  240. }
  241. - (void)updateSublabel {
  242. [self updateSublabelAndBeginScroll:YES];
  243. }
  244. - (void)updateSublabelAndBeginScroll:(BOOL)beginScroll {
  245. if (!self.subLabel.text || !self.superview) {
  246. return;
  247. }
  248. // Calculate expected size
  249. CGSize expectedLabelSize = [self subLabelSize];
  250. // Invalidate intrinsic size
  251. [self invalidateIntrinsicContentSize];
  252. // Move to home
  253. [self returnLabelToOriginImmediately];
  254. // Configure gradient for the current condition
  255. [self applyGradientMaskForFadeLength:self.fadeLength animated:YES];
  256. // Check if label should scroll
  257. // Can be because: 1) text fits, or 2) labelization
  258. // The holdScrolling property does NOT affect this
  259. if (!self.labelShouldScroll) {
  260. // Set text alignment and break mode to act like normal label
  261. self.subLabel.textAlignment = [super textAlignment];
  262. self.subLabel.lineBreakMode = [super lineBreakMode];
  263. CGRect labelFrame, unusedFrame;
  264. switch (self.marqueeType) {
  265. case MLContinuousReverse:
  266. case MLRightLeft:
  267. case MLRight:
  268. CGRectDivide(self.bounds, &unusedFrame, &labelFrame, self.leadingBuffer, CGRectMaxXEdge);
  269. labelFrame = CGRectIntegral(labelFrame);
  270. break;
  271. default:
  272. labelFrame = CGRectIntegral(CGRectMake(self.leadingBuffer, 0.0f, self.bounds.size.width - self.leadingBuffer, self.bounds.size.height));
  273. break;
  274. }
  275. self.homeLabelFrame = labelFrame;
  276. self.awayOffset = 0.0f;
  277. // Remove an additional sublabels (for continuous types)
  278. self.repliLayer.instanceCount = 1;
  279. // Set sublabel frame calculated labelFrame
  280. self.subLabel.frame = labelFrame;
  281. // Remove fade, as by definition none is needed in this case
  282. [self removeGradientMask];
  283. return;
  284. }
  285. // Label DOES need to scroll
  286. [self.subLabel setLineBreakMode:NSLineBreakByClipping];
  287. // Spacing between primary and second sublabel must be at least equal to leadingBuffer, and at least equal to the fadeLength
  288. CGFloat minTrailing = MAX(MAX(self.leadingBuffer, self.trailingBuffer), self.fadeLength);
  289. switch (self.marqueeType) {
  290. case MLContinuous:
  291. case MLContinuousReverse:
  292. {
  293. if (self.marqueeType == MLContinuous) {
  294. self.homeLabelFrame = CGRectIntegral(CGRectMake(self.leadingBuffer, 0.0f, expectedLabelSize.width, self.bounds.size.height));
  295. self.awayOffset = -(self.homeLabelFrame.size.width + minTrailing);
  296. } else {
  297. self.homeLabelFrame = CGRectIntegral(CGRectMake(self.bounds.size.width - (expectedLabelSize.width + self.leadingBuffer), 0.0f, expectedLabelSize.width, self.bounds.size.height));
  298. self.awayOffset = (self.homeLabelFrame.size.width + minTrailing);
  299. }
  300. self.subLabel.frame = self.homeLabelFrame;
  301. // Configure replication
  302. self.repliLayer.instanceCount = 2;
  303. self.repliLayer.instanceTransform = CATransform3DMakeTranslation(-self.awayOffset, 0.0, 0.0);
  304. // Recompute the animation duration
  305. self.animationDuration = (self.rate != 0) ? ((NSTimeInterval) fabs(self.awayOffset) / self.rate) : (self.scrollDuration);
  306. break;
  307. }
  308. case MLRightLeft:
  309. case MLRight:
  310. {
  311. self.homeLabelFrame = CGRectIntegral(CGRectMake(self.bounds.size.width - (expectedLabelSize.width + self.leadingBuffer), 0.0f, expectedLabelSize.width, self.bounds.size.height));
  312. self.awayOffset = (expectedLabelSize.width + self.trailingBuffer + self.leadingBuffer) - self.bounds.size.width;
  313. // Calculate animation duration
  314. self.animationDuration = (self.rate != 0) ? (NSTimeInterval)fabs(self.awayOffset / self.rate) : (self.scrollDuration);
  315. // Set frame and text
  316. self.subLabel.frame = self.homeLabelFrame;
  317. // Remove any replication
  318. self.repliLayer.instanceCount = 1;
  319. // Enforce text alignment for this type
  320. self.subLabel.textAlignment = NSTextAlignmentRight;
  321. break;
  322. }
  323. case MLLeftRight:
  324. case MLLeft:
  325. {
  326. self.homeLabelFrame = CGRectIntegral(CGRectMake(self.leadingBuffer, 0.0f, expectedLabelSize.width, self.bounds.size.height));
  327. self.awayOffset = self.bounds.size.width - (expectedLabelSize.width + self.leadingBuffer + self.trailingBuffer);
  328. // Calculate animation duration
  329. self.animationDuration = (self.rate != 0) ? (NSTimeInterval)fabs(self.awayOffset / self.rate) : (self.scrollDuration);
  330. // Set frame
  331. self.subLabel.frame = self.homeLabelFrame;
  332. // Remove any replication
  333. self.repliLayer.instanceCount = 1;
  334. // Enforce text alignment for this type
  335. self.subLabel.textAlignment = NSTextAlignmentLeft;
  336. break;
  337. }
  338. default:
  339. {
  340. // Something strange has happened
  341. self.homeLabelFrame = CGRectZero;
  342. self.awayOffset = 0.0f;
  343. // Do not attempt to begin scroll
  344. return;
  345. break;
  346. }
  347. } //end of marqueeType switch
  348. if (!self.tapToScroll && !self.holdScrolling && beginScroll) {
  349. [self beginScroll];
  350. }
  351. }
  352. - (CGSize)subLabelSize {
  353. // Calculate expected size
  354. CGSize expectedLabelSize = CGSizeZero;
  355. CGSize maximumLabelSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
  356. // Get size of subLabel
  357. expectedLabelSize = [self.subLabel sizeThatFits:maximumLabelSize];
  358. #ifdef TARGET_OS_IOS
  359. // Sanitize width to 5461.0f (largest width a UILabel will draw on an iPhone 6S Plus)
  360. expectedLabelSize.width = MIN(expectedLabelSize.width, 5461.0f);
  361. #elif TARGET_OS_TV
  362. // Sanitize width to 16384.0 (largest width a UILabel will draw on tvOS)
  363. expectedLabelSize.width = MIN(expectedLabelSize.width, 16384.0f);
  364. #endif
  365. // Adjust to own height (make text baseline match normal label)
  366. expectedLabelSize.height = self.bounds.size.height;
  367. return expectedLabelSize;
  368. }
  369. - (CGSize)sizeThatFits:(CGSize)size {
  370. CGSize fitSize = [self.subLabel sizeThatFits:size];
  371. fitSize.width += self.leadingBuffer;
  372. return fitSize;
  373. }
  374. #pragma mark - Animation Handlers
  375. - (BOOL)labelShouldScroll {
  376. BOOL stringLength = ([self.subLabel.text length] > 0);
  377. if (!stringLength) {
  378. return NO;
  379. }
  380. BOOL labelTooLarge = ([self subLabelSize].width + self.leadingBuffer > self.bounds.size.width + FLT_EPSILON);
  381. BOOL animationHasDuration = (self.scrollDuration > 0.0f || self.rate > 0.0f);
  382. return (!self.labelize && labelTooLarge && animationHasDuration);
  383. }
  384. - (BOOL)labelReadyForScroll {
  385. // Check if we have a superview
  386. if (!self.superview) {
  387. return NO;
  388. }
  389. if (!self.window) {
  390. return NO;
  391. }
  392. // Check if our view controller is ready
  393. UIViewController *viewController = [self firstAvailableViewController];
  394. if (!viewController.isViewLoaded) {
  395. return NO;
  396. }
  397. return YES;
  398. }
  399. - (void)beginScroll {
  400. [self beginScrollWithDelay:YES];
  401. }
  402. - (void)beginScrollWithDelay:(BOOL)delay {
  403. switch (self.marqueeType) {
  404. case MLContinuous:
  405. case MLContinuousReverse:
  406. [self scrollContinuousWithInterval:self.animationDuration after:(delay ? self.animationDelay : 0.0)];
  407. break;
  408. case MLLeft:
  409. case MLRight:
  410. [self scrollAwayWithInterval:self.animationDuration delayAmount:(delay ? self.animationDelay : 0.0) shouldReturn:NO];
  411. break;
  412. default:
  413. [self scrollAwayWithInterval:self.animationDuration];
  414. break;
  415. }
  416. }
  417. - (void)returnLabelToOriginImmediately {
  418. // Remove gradient animations
  419. [self.layer.mask removeAllAnimations];
  420. // Remove sublabel position animations
  421. [self.subLabel.layer removeAllAnimations];
  422. // Remove compeltion blocks
  423. self.scrollCompletionBlock = nil;
  424. }
  425. - (void)scrollAwayWithInterval:(NSTimeInterval)interval {
  426. [self scrollAwayWithInterval:interval delay:YES];
  427. }
  428. - (void)scrollAwayWithInterval:(NSTimeInterval)interval delay:(BOOL)delay {
  429. [self scrollAwayWithInterval:interval delayAmount:(delay ? self.animationDelay : 0.0) shouldReturn:YES];
  430. }
  431. - (void)scrollAwayWithInterval:(NSTimeInterval)interval delayAmount:(NSTimeInterval)delayAmount shouldReturn:(BOOL)shouldReturn {
  432. // Check for conditions which would prevent scrolling
  433. if (![self labelReadyForScroll]) {
  434. return;
  435. }
  436. // Return labels to home (cancel any animations)
  437. [self returnLabelToOriginImmediately];
  438. // Call pre-animation method
  439. [self labelWillBeginScroll];
  440. // Animate
  441. [CATransaction begin];
  442. // Set Duration
  443. [CATransaction setAnimationDuration:(!shouldReturn ? CGFLOAT_MAX : 2.0 * (delayAmount + interval))];
  444. // Create animation for gradient, if needed
  445. if (self.fadeLength != 0.0f) {
  446. CAKeyframeAnimation *gradAnim = [self keyFrameAnimationForGradientFadeLength:self.fadeLength
  447. interval:interval
  448. delay:delayAmount];
  449. [self.layer.mask addAnimation:gradAnim forKey:@"gradient"];
  450. }
  451. __weak __typeof__(self) weakSelf = self;
  452. self.scrollCompletionBlock = ^(BOOL finished) {
  453. if (!finished || !weakSelf) {
  454. // Do not continue into the next loop
  455. return;
  456. }
  457. // Call returned home method
  458. [weakSelf labelReturnedToHome:YES];
  459. // Check to ensure that:
  460. // 1) We don't double fire if an animation already exists
  461. // 2) The instance is still attached to a window - this completion block is called for
  462. // many reasons, including if the animation is removed due to the view being removed
  463. // from the UIWindow (typically when the view controller is no longer the "top" view)
  464. if (self.window && ![weakSelf.subLabel.layer animationForKey:@"position"]) {
  465. // Begin again, if conditions met
  466. if (weakSelf.labelShouldScroll && !weakSelf.tapToScroll && !weakSelf.holdScrolling) {
  467. [weakSelf scrollAwayWithInterval:interval delayAmount:delayAmount shouldReturn:shouldReturn];
  468. }
  469. }
  470. };
  471. // Create animation for position
  472. CGPoint homeOrigin = self.homeLabelFrame.origin;
  473. CGPoint awayOrigin = MLOffsetCGPoint(self.homeLabelFrame.origin, self.awayOffset);
  474. NSArray *values = nil;
  475. switch (self.marqueeType) {
  476. case MLLeft:
  477. case MLRight:
  478. values = @[[NSValue valueWithCGPoint:homeOrigin], // Initial location, home
  479. [NSValue valueWithCGPoint:homeOrigin], // Initial delay, at home
  480. [NSValue valueWithCGPoint:awayOrigin], // Animation to away
  481. [NSValue valueWithCGPoint:awayOrigin]]; // Delay at away
  482. break;
  483. default:
  484. values = @[[NSValue valueWithCGPoint:homeOrigin], // Initial location, home
  485. [NSValue valueWithCGPoint:homeOrigin], // Initial delay, at home
  486. [NSValue valueWithCGPoint:awayOrigin], // Animation to away
  487. [NSValue valueWithCGPoint:awayOrigin], // Delay at away
  488. [NSValue valueWithCGPoint:homeOrigin]]; // Animation to home
  489. break;
  490. }
  491. CAKeyframeAnimation *awayAnim = [self keyFrameAnimationForProperty:@"position"
  492. values:values
  493. interval:interval
  494. delay:delayAmount];
  495. // Add completion block
  496. [awayAnim setValue:@(YES) forKey:kMarqueeLabelAnimationCompletionBlock];
  497. // Add animation
  498. [self.subLabel.layer addAnimation:awayAnim forKey:@"position"];
  499. [CATransaction commit];
  500. }
  501. - (void)scrollContinuousWithInterval:(NSTimeInterval)interval after:(NSTimeInterval)delayAmount {
  502. [self scrollContinuousWithInterval:interval after:delayAmount labelAnimation:nil gradientAnimation:nil];
  503. }
  504. - (void)scrollContinuousWithInterval:(NSTimeInterval)interval
  505. after:(NSTimeInterval)delayAmount
  506. labelAnimation:(CAKeyframeAnimation *)labelAnimation
  507. gradientAnimation:(CAKeyframeAnimation *)gradientAnimation {
  508. // Check for conditions which would prevent scrolling
  509. if (![self labelReadyForScroll]) {
  510. return;
  511. }
  512. // Return labels to home (cancel any animations)
  513. [self returnLabelToOriginImmediately];
  514. // Call pre-animation method
  515. [self labelWillBeginScroll];
  516. // Animate
  517. [CATransaction begin];
  518. // Set Duration
  519. [CATransaction setAnimationDuration:(delayAmount + interval)];
  520. // Create animation for gradient, if needed
  521. if (self.fadeLength != 0.0f) {
  522. if (!gradientAnimation) {
  523. gradientAnimation = [self keyFrameAnimationForGradientFadeLength:self.fadeLength
  524. interval:interval
  525. delay:delayAmount];
  526. }
  527. [self.layer.mask addAnimation:gradientAnimation forKey:@"gradient"];
  528. }
  529. // Create animation for sublabel positions, if needed
  530. if (!labelAnimation) {
  531. CGPoint homeOrigin = self.homeLabelFrame.origin;
  532. CGPoint awayOrigin = MLOffsetCGPoint(self.homeLabelFrame.origin, self.awayOffset);
  533. NSArray *values = @[[NSValue valueWithCGPoint:homeOrigin], // Initial location, home
  534. [NSValue valueWithCGPoint:homeOrigin], // Initial delay, at home
  535. [NSValue valueWithCGPoint:awayOrigin]]; // Animation to home
  536. labelAnimation = [self keyFrameAnimationForProperty:@"position"
  537. values:values
  538. interval:interval
  539. delay:delayAmount];
  540. }
  541. __weak __typeof__(self) weakSelf = self;
  542. self.scrollCompletionBlock = ^(BOOL finished) {
  543. if (!finished || !weakSelf) {
  544. // Do not continue into the next loop
  545. return;
  546. }
  547. // Call returned home method
  548. [weakSelf labelReturnedToHome:YES];
  549. // Check to ensure that:
  550. // 1) We don't double fire if an animation already exists
  551. // 2) The instance is still attached to a window - this completion block is called for
  552. // many reasons, including if the animation is removed due to the view being removed
  553. // from the UIWindow (typically when the view controller is no longer the "top" view)
  554. if (weakSelf.window && ![weakSelf.subLabel.layer animationForKey:@"position"]) {
  555. // Begin again, if conditions met
  556. if (weakSelf.labelShouldScroll && !weakSelf.tapToScroll && !weakSelf.holdScrolling) {
  557. [weakSelf scrollContinuousWithInterval:interval
  558. after:delayAmount
  559. labelAnimation:labelAnimation
  560. gradientAnimation:gradientAnimation];
  561. }
  562. }
  563. };
  564. // Attach completion block
  565. [labelAnimation setValue:@(YES) forKey:kMarqueeLabelAnimationCompletionBlock];
  566. // Add animation
  567. [self.subLabel.layer addAnimation:labelAnimation forKey:@"position"];
  568. [CATransaction commit];
  569. }
  570. - (void)applyGradientMaskForFadeLength:(CGFloat)fadeLength animated:(BOOL)animated {
  571. // Remove any in-flight animations
  572. [self.layer.mask removeAllAnimations];
  573. // Check for zero-length fade
  574. if (fadeLength <= 0.0f) {
  575. [self removeGradientMask];
  576. return;
  577. }
  578. // Configure gradient mask without implicit animations
  579. [CATransaction begin];
  580. [CATransaction setDisableActions:YES];
  581. CAGradientLayer *gradientMask = (CAGradientLayer *)self.layer.mask;
  582. // Set up colors
  583. NSObject *transparent = (NSObject *)[[UIColor clearColor] CGColor];
  584. NSObject *opaque = (NSObject *)[[UIColor blackColor] CGColor];
  585. if (!gradientMask) {
  586. // Create CAGradientLayer if needed
  587. gradientMask = [CAGradientLayer layer];
  588. gradientMask.shouldRasterize = YES;
  589. gradientMask.rasterizationScale = [UIScreen mainScreen].scale;
  590. gradientMask.startPoint = CGPointMake(0.0f, 0.5f);
  591. gradientMask.endPoint = CGPointMake(1.0f, 0.5f);
  592. }
  593. // Check if there is a mask-to-bounds size mismatch
  594. if (!CGRectEqualToRect(gradientMask.bounds, self.bounds)) {
  595. // Adjust stops based on fade length
  596. CGFloat leftFadeStop = fadeLength/self.bounds.size.width;
  597. CGFloat rightFadeStop = fadeLength/self.bounds.size.width;
  598. gradientMask.locations = @[@(0.0f), @(leftFadeStop), @(1.0f - rightFadeStop), @(1.0f)];
  599. }
  600. gradientMask.bounds = self.layer.bounds;
  601. gradientMask.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  602. // Set mask
  603. self.layer.mask = gradientMask;
  604. // Determine colors for non-scrolling label (i.e. at home)
  605. NSArray *adjustedColors;
  606. BOOL trailingFadeNeeded = self.labelShouldScroll;
  607. switch (self.marqueeType) {
  608. case MLContinuousReverse:
  609. case MLRightLeft:
  610. case MLRight:
  611. adjustedColors = @[(trailingFadeNeeded ? transparent : opaque),
  612. opaque,
  613. opaque,
  614. opaque];
  615. break;
  616. default:
  617. // MLContinuous
  618. // MLLeftRight
  619. adjustedColors = @[opaque,
  620. opaque,
  621. opaque,
  622. (trailingFadeNeeded ? transparent : opaque)];
  623. break;
  624. }
  625. // Check for IBDesignable
  626. #if TARGET_INTERFACE_BUILDER
  627. animated = NO;
  628. #endif
  629. if (animated) {
  630. // Finish transaction
  631. [CATransaction commit];
  632. // Create animation for color change
  633. GradientSetupAnimation *colorAnimation = [GradientSetupAnimation animationWithKeyPath:@"colors"];
  634. colorAnimation.fromValue = gradientMask.colors;
  635. colorAnimation.toValue = adjustedColors;
  636. colorAnimation.duration = 0.25;
  637. colorAnimation.removedOnCompletion = NO;
  638. colorAnimation.delegate = self;
  639. [gradientMask addAnimation:colorAnimation forKey:@"setupFade"];
  640. } else {
  641. gradientMask.colors = adjustedColors;
  642. [CATransaction commit];
  643. }
  644. }
  645. - (void)removeGradientMask {
  646. self.layer.mask = nil;
  647. }
  648. - (CAKeyframeAnimation *)keyFrameAnimationForGradientFadeLength:(CGFloat)fadeLength
  649. interval:(NSTimeInterval)interval
  650. delay:(NSTimeInterval)delayAmount
  651. {
  652. // Setup
  653. NSArray *values = nil;
  654. NSArray *keyTimes = nil;
  655. NSTimeInterval totalDuration;
  656. NSObject *transp = (NSObject *)[[UIColor clearColor] CGColor];
  657. NSObject *opaque = (NSObject *)[[UIColor blackColor] CGColor];
  658. // Create new animation
  659. CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"colors"];
  660. // Get timing function
  661. CAMediaTimingFunction *timingFunction = [self timingFunctionForAnimationOptions:self.animationCurve];
  662. // Define keyTimes
  663. switch (self.marqueeType) {
  664. case MLLeftRight:
  665. case MLRightLeft:
  666. // Calculate total animation duration
  667. totalDuration = 2.0 * (delayAmount + interval);
  668. keyTimes = @[@(0.0), // 1) Initial gradient
  669. @(delayAmount/totalDuration), // 2) Begin of LE fade-in, just as scroll away starts
  670. @((delayAmount + 0.4)/totalDuration), // 3) End of LE fade in [LE fully faded]
  671. @((delayAmount + interval - 0.4)/totalDuration), // 4) Begin of TE fade out, just before scroll away finishes
  672. @((delayAmount + interval)/totalDuration), // 5) End of TE fade out [TE fade removed]
  673. @((delayAmount + interval + delayAmount)/totalDuration), // 6) Begin of TE fade back in, just as scroll home starts
  674. @((delayAmount + interval + delayAmount + 0.4)/totalDuration), // 7) End of TE fade back in [TE fully faded]
  675. @((totalDuration - 0.4)/totalDuration), // 8) Begin of LE fade out, just before scroll home finishes
  676. @(1.0)]; // 9) End of LE fade out, just as scroll home finishes
  677. break;
  678. case MLLeft:
  679. case MLRight:
  680. // Calculate total animation duration
  681. totalDuration = CGFLOAT_MAX;
  682. keyTimes = @[@(0.0), // 1) Initial gradient
  683. @(delayAmount/totalDuration), // 2) Begin of LE fade-in, just as scroll away starts
  684. @((delayAmount + 0.4)/totalDuration), // 3) End of LE fade in [LE fully faded]
  685. @((delayAmount + interval - 0.4)/totalDuration), // 4) Begin of TE fade out, just before scroll away finishes
  686. @((delayAmount + interval)/totalDuration), // 5) End of TE fade out [TE fade removed]
  687. @(1.0)];
  688. break;
  689. case MLContinuousReverse:
  690. default:
  691. // Calculate total animation duration
  692. totalDuration = delayAmount + interval;
  693. // Find when the lead label will be totally offscreen
  694. CGFloat startFadeFraction = fabs((self.subLabel.bounds.size.width + self.leadingBuffer) / self.awayOffset);
  695. // Find when the animation will hit that point
  696. CGFloat startFadeTimeFraction = [timingFunction durationPercentageForPositionPercentage:startFadeFraction withDuration:totalDuration];
  697. NSTimeInterval startFadeTime = delayAmount + startFadeTimeFraction * interval;
  698. keyTimes = @[
  699. @(0.0), // Initial gradient
  700. @(delayAmount/totalDuration), // Begin of fade in
  701. @((delayAmount + 0.2)/totalDuration), // End of fade in, just as scroll away starts
  702. @((startFadeTime)/totalDuration), // Begin of fade out, just before scroll home completes
  703. @((startFadeTime + 0.1)/totalDuration), // End of fade out, as scroll home completes
  704. @(1.0) // Buffer final value (used on continuous types)
  705. ];
  706. break;
  707. }
  708. // Define gradient values
  709. // Get curent layer values
  710. CAGradientLayer *currentMask = [[self maskLayer] presentationLayer];
  711. NSArray *currentValues = currentMask.colors;
  712. switch (self.marqueeType) {
  713. case MLContinuousReverse:
  714. values = @[
  715. (currentValues ? currentValues : @[transp, opaque, opaque, opaque]), // Initial gradient
  716. @[transp, opaque, opaque, opaque], // Begin of fade in
  717. @[transp, opaque, opaque, transp], // End of fade in, just as scroll away starts
  718. @[transp, opaque, opaque, transp], // Begin of fade out, just before scroll home completes
  719. @[transp, opaque, opaque, opaque], // End of fade out, as scroll home completes
  720. @[transp, opaque, opaque, opaque] // Final "home" value
  721. ];
  722. break;
  723. case MLRight:
  724. values = @[
  725. (currentValues ? currentValues : @[transp, opaque, opaque, opaque]), // 1)
  726. @[transp, opaque, opaque, opaque], // 2)
  727. @[transp, opaque, opaque, transp], // 3)
  728. @[transp, opaque, opaque, transp], // 4)
  729. @[opaque, opaque, opaque, transp], // 5)
  730. @[opaque, opaque, opaque, transp], // 6)
  731. ];
  732. break;
  733. case MLRightLeft:
  734. values = @[
  735. (currentValues ? currentValues : @[transp, opaque, opaque, opaque]), // 1)
  736. @[transp, opaque, opaque, opaque], // 2)
  737. @[transp, opaque, opaque, transp], // 3)
  738. @[transp, opaque, opaque, transp], // 4)
  739. @[opaque, opaque, opaque, transp], // 5)
  740. @[opaque, opaque, opaque, transp], // 6)
  741. @[transp, opaque, opaque, transp], // 7)
  742. @[transp, opaque, opaque, transp], // 8)
  743. @[transp, opaque, opaque, opaque] // 9)
  744. ];
  745. break;
  746. case MLContinuous:
  747. values = @[
  748. (currentValues ? currentValues : @[opaque, opaque, opaque, transp]), // Initial gradient
  749. @[opaque, opaque, opaque, transp], // Begin of fade in
  750. @[transp, opaque, opaque, transp], // End of fade in, just as scroll away starts
  751. @[transp, opaque, opaque, transp], // Begin of fade out, just before scroll home completes
  752. @[opaque, opaque, opaque, transp], // End of fade out, as scroll home completes
  753. @[opaque, opaque, opaque, transp] // Final "home" value
  754. ];
  755. break;
  756. case MLLeft:
  757. values = @[
  758. (currentValues ? currentValues : @[opaque, opaque, opaque, transp]), // 1)
  759. @[opaque, opaque, opaque, transp], // 2)
  760. @[transp, opaque, opaque, transp], // 3)
  761. @[transp, opaque, opaque, transp], // 4)
  762. @[transp, opaque, opaque, opaque], // 5)
  763. @[transp, opaque, opaque, opaque], // 6)
  764. ];
  765. break;
  766. case MLLeftRight:
  767. default:
  768. values = @[
  769. (currentValues ? currentValues : @[opaque, opaque, opaque, transp]), // 1)
  770. @[opaque, opaque, opaque, transp], // 2)
  771. @[transp, opaque, opaque, transp], // 3)
  772. @[transp, opaque, opaque, transp], // 4)
  773. @[transp, opaque, opaque, opaque], // 5)
  774. @[transp, opaque, opaque, opaque], // 6)
  775. @[transp, opaque, opaque, transp], // 7)
  776. @[transp, opaque, opaque, transp], // 8)
  777. @[opaque, opaque, opaque, transp] // 9)
  778. ];
  779. break;
  780. }
  781. animation.values = values;
  782. animation.keyTimes = keyTimes;
  783. animation.timingFunctions = @[timingFunction, timingFunction, timingFunction, timingFunction];
  784. return animation;
  785. }
  786. - (CAKeyframeAnimation *)keyFrameAnimationForProperty:(NSString *)property
  787. values:(NSArray *)values
  788. interval:(NSTimeInterval)interval
  789. delay:(NSTimeInterval)delayAmount
  790. {
  791. // Create new animation
  792. CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:property];
  793. // Get timing function
  794. CAMediaTimingFunction *timingFunction = [self timingFunctionForAnimationOptions:self.animationCurve];
  795. // Calculate times based on marqueeType
  796. NSTimeInterval totalDuration;
  797. switch (self.marqueeType) {
  798. case MLLeftRight:
  799. case MLRightLeft:
  800. NSAssert(values.count == 5, @"Incorrect number of values passed for MLLeftRight-type animation");
  801. totalDuration = 2.0 * (delayAmount + interval);
  802. // Set up keyTimes
  803. animation.keyTimes = @[@(0.0), // Initial location, home
  804. @(delayAmount/totalDuration), // Initial delay, at home
  805. @((delayAmount + interval)/totalDuration), // Animation to away
  806. @((delayAmount + interval + delayAmount)/totalDuration), // Delay at away
  807. @(1.0)]; // Animation to home
  808. animation.timingFunctions = @[timingFunction,
  809. timingFunction,
  810. timingFunction,
  811. timingFunction];
  812. break;
  813. case MLLeft:
  814. case MLRight:
  815. NSAssert(values.count == 4, @"Incorrect number of values passed for MLLeft-type animation");
  816. totalDuration = CGFLOAT_MAX;
  817. // Set up keyTimes
  818. animation.keyTimes = @[@(0.0), // Initial location, home
  819. @(delayAmount/totalDuration), // Initial delay, at home
  820. @((delayAmount + interval)/totalDuration), // Animation to away
  821. @(1.0)]; // Animation to home
  822. animation.timingFunctions = @[timingFunction,
  823. timingFunction,
  824. timingFunction];
  825. break;
  826. // MLContinuous
  827. // MLContinuousReverse
  828. default:
  829. NSAssert(values.count == 3, @"Incorrect number of values passed for MLContinous-type animation");
  830. totalDuration = delayAmount + interval;
  831. // Set up keyTimes
  832. animation.keyTimes = @[@(0.0), // Initial location, home
  833. @(delayAmount/totalDuration), // Initial delay, at home
  834. @(1.0)]; // Animation to away
  835. animation.timingFunctions = @[timingFunction,
  836. timingFunction];
  837. break;
  838. }
  839. // Set values
  840. animation.values = values;
  841. animation.delegate = self;
  842. return animation;
  843. }
  844. - (CAMediaTimingFunction *)timingFunctionForAnimationOptions:(UIViewAnimationOptions)animationOptions {
  845. NSString *timingFunction;
  846. switch (animationOptions) {
  847. case UIViewAnimationOptionCurveEaseIn:
  848. timingFunction = kCAMediaTimingFunctionEaseIn;
  849. break;
  850. case UIViewAnimationOptionCurveEaseInOut:
  851. timingFunction = kCAMediaTimingFunctionEaseInEaseOut;
  852. break;
  853. case UIViewAnimationOptionCurveEaseOut:
  854. timingFunction = kCAMediaTimingFunctionEaseOut;
  855. break;
  856. default:
  857. timingFunction = kCAMediaTimingFunctionLinear;
  858. break;
  859. }
  860. return [CAMediaTimingFunction functionWithName:timingFunction];
  861. }
  862. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
  863. if ([anim isMemberOfClass:[GradientSetupAnimation class]]) {
  864. GradientSetupAnimation *setupFade = (GradientSetupAnimation *)anim;
  865. NSArray *finalColors = setupFade.toValue;
  866. if (finalColors) {
  867. [(CAGradientLayer *)self.layer.mask setColors:finalColors];
  868. }
  869. // Remove any/all setupFade animations regardless
  870. [self.layer.mask removeAnimationForKey:@"setupFade"];
  871. } else {
  872. if (self.scrollCompletionBlock) {
  873. self.scrollCompletionBlock(flag);
  874. }
  875. }
  876. }
  877. #pragma mark - Label Control
  878. - (void)restartLabel {
  879. // Shutdown the label
  880. [self shutdownLabel];
  881. // Restart scrolling if appropriate
  882. if (self.labelShouldScroll && !self.tapToScroll && !self.holdScrolling) {
  883. [self beginScroll];
  884. }
  885. }
  886. - (void)resetLabel {
  887. [self returnLabelToOriginImmediately];
  888. self.homeLabelFrame = CGRectNull;
  889. self.awayOffset = 0.0f;
  890. }
  891. - (void)shutdownLabel {
  892. // Bring label to home location
  893. [self returnLabelToOriginImmediately];
  894. // Apply gradient mask for home location
  895. [self applyGradientMaskForFadeLength:self.fadeLength animated:false];
  896. }
  897. -(void)pauseLabel
  898. {
  899. // Only pause if label is not already paused, and already in a scrolling animation
  900. if (!self.isPaused && self.awayFromHome) {
  901. // Pause sublabel position animation
  902. CFTimeInterval labelPauseTime = [self.subLabel.layer convertTime:CACurrentMediaTime() fromLayer:nil];
  903. self.subLabel.layer.speed = 0.0;
  904. self.subLabel.layer.timeOffset = labelPauseTime;
  905. // Pause gradient fade animation
  906. CFTimeInterval gradientPauseTime = [self.layer.mask convertTime:CACurrentMediaTime() fromLayer:nil];
  907. self.layer.mask.speed = 0.0;
  908. self.layer.mask.timeOffset = gradientPauseTime;
  909. self.isPaused = YES;
  910. }
  911. }
  912. -(void)unpauseLabel
  913. {
  914. if (self.isPaused) {
  915. // Unpause sublabel position animation
  916. CFTimeInterval labelPausedTime = self.subLabel.layer.timeOffset;
  917. self.subLabel.layer.speed = 1.0;
  918. self.subLabel.layer.timeOffset = 0.0;
  919. self.subLabel.layer.beginTime = 0.0;
  920. self.subLabel.layer.beginTime = [self.subLabel.layer convertTime:CACurrentMediaTime() fromLayer:nil] - labelPausedTime;
  921. // Unpause gradient fade animation
  922. CFTimeInterval gradientPauseTime = self.layer.mask.timeOffset;
  923. self.layer.mask.speed = 1.0;
  924. self.layer.mask.timeOffset = 0.0;
  925. self.layer.mask.beginTime = 0.0;
  926. self.layer.mask.beginTime = [self.layer.mask convertTime:CACurrentMediaTime() fromLayer:nil] - gradientPauseTime;
  927. self.isPaused = NO;
  928. }
  929. }
  930. - (void)labelWasTapped:(UITapGestureRecognizer *)recognizer {
  931. if (self.labelShouldScroll && !self.awayFromHome) {
  932. [self beginScrollWithDelay:NO];
  933. }
  934. }
  935. - (void)triggerScrollStart {
  936. if (self.labelShouldScroll && !self.awayFromHome) {
  937. [self beginScroll];
  938. }
  939. }
  940. - (void)labelWillBeginScroll {
  941. // Default implementation does nothing
  942. return;
  943. }
  944. - (void)labelReturnedToHome:(BOOL)finished {
  945. // Default implementation does nothing
  946. return;
  947. }
  948. #pragma mark - Modified UIView Methods/Getters/Setters
  949. - (void)setFrame:(CGRect)frame {
  950. [super setFrame:frame];
  951. // Check if device is running iOS 8.0.X
  952. if(SYSTEM_VERSION_IS_8_0_X) {
  953. // If so, force update because layoutSubviews is not called
  954. [self updateSublabel];
  955. }
  956. }
  957. - (void)setBounds:(CGRect)bounds {
  958. [super setBounds:bounds];
  959. // Check if device is running iOS 8.0.X
  960. if(SYSTEM_VERSION_IS_8_0_X) {
  961. // If so, force update because layoutSubviews is not called
  962. [self updateSublabel];
  963. }
  964. }
  965. #pragma mark - Modified UILabel Methods/Getters/Setters
  966. - (UIView *)viewForBaselineLayout {
  967. // Use subLabel view for handling baseline layouts
  968. return self.subLabel;
  969. }
  970. - (UIView *)viewForLastBaselineLayout {
  971. // Use subLabel view for handling baseline layouts
  972. return self.subLabel;
  973. }
  974. - (UIView *)viewForFirstBaselineLayout {
  975. // Use subLabel view for handling baseline layouts
  976. return self.subLabel;
  977. }
  978. - (NSString *)text {
  979. return self.subLabel.text;
  980. }
  981. - (void)setText:(NSString *)text {
  982. if ([text isEqualToString:self.subLabel.text]) {
  983. return;
  984. }
  985. self.subLabel.text = text;
  986. super.text = text;
  987. [self updateSublabel];
  988. }
  989. - (NSAttributedString *)attributedText {
  990. return self.subLabel.attributedText;
  991. }
  992. - (void)setAttributedText:(NSAttributedString *)attributedText {
  993. if ([attributedText isEqualToAttributedString:self.subLabel.attributedText]) {
  994. return;
  995. }
  996. self.subLabel.attributedText = attributedText;
  997. super.attributedText = attributedText;
  998. [self updateSublabel];
  999. }
  1000. - (UIFont *)font {
  1001. return self.subLabel.font;
  1002. }
  1003. - (void)setFont:(UIFont *)font {
  1004. if ([font isEqual:self.subLabel.font]) {
  1005. return;
  1006. }
  1007. self.subLabel.font = font;
  1008. super.font = font;
  1009. [self updateSublabel];
  1010. }
  1011. - (UIColor *)textColor {
  1012. return self.subLabel.textColor;
  1013. }
  1014. - (void)setTextColor:(UIColor *)textColor {
  1015. self.subLabel.textColor = textColor;
  1016. super.textColor = textColor;
  1017. }
  1018. - (UIColor *)backgroundColor {
  1019. return self.subLabel.backgroundColor;
  1020. }
  1021. - (void)setBackgroundColor:(UIColor *)backgroundColor {
  1022. self.subLabel.backgroundColor = backgroundColor;
  1023. super.backgroundColor = backgroundColor;
  1024. }
  1025. - (UIColor *)shadowColor {
  1026. return self.subLabel.shadowColor;
  1027. }
  1028. - (void)setShadowColor:(UIColor *)shadowColor {
  1029. self.subLabel.shadowColor = shadowColor;
  1030. super.shadowColor = shadowColor;
  1031. }
  1032. - (CGSize)shadowOffset {
  1033. return self.subLabel.shadowOffset;
  1034. }
  1035. - (void)setShadowOffset:(CGSize)shadowOffset {
  1036. self.subLabel.shadowOffset = shadowOffset;
  1037. super.shadowOffset = shadowOffset;
  1038. }
  1039. - (UIColor *)highlightedTextColor {
  1040. return self.subLabel.highlightedTextColor;
  1041. }
  1042. - (void)setHighlightedTextColor:(UIColor *)highlightedTextColor {
  1043. self.subLabel.highlightedTextColor = highlightedTextColor;
  1044. super.highlightedTextColor = highlightedTextColor;
  1045. }
  1046. - (BOOL)isHighlighted {
  1047. return self.subLabel.isHighlighted;
  1048. }
  1049. - (void)setHighlighted:(BOOL)highlighted {
  1050. self.subLabel.highlighted = highlighted;
  1051. super.highlighted = highlighted;
  1052. }
  1053. - (BOOL)isEnabled {
  1054. return self.subLabel.isEnabled;
  1055. }
  1056. - (void)setEnabled:(BOOL)enabled {
  1057. self.subLabel.enabled = enabled;
  1058. super.enabled = enabled;
  1059. }
  1060. - (void)setNumberOfLines:(NSInteger)numberOfLines {
  1061. // By the nature of MarqueeLabel, this is 1
  1062. [super setNumberOfLines:1];
  1063. }
  1064. - (void)setAdjustsFontSizeToFitWidth:(BOOL)adjustsFontSizeToFitWidth {
  1065. // By the nature of MarqueeLabel, this is NO
  1066. [super setAdjustsFontSizeToFitWidth:NO];
  1067. }
  1068. - (void)setMinimumFontSize:(CGFloat)minimumFontSize {
  1069. [super setMinimumFontSize:0.0];
  1070. }
  1071. - (UIBaselineAdjustment)baselineAdjustment {
  1072. return self.subLabel.baselineAdjustment;
  1073. }
  1074. - (void)setBaselineAdjustment:(UIBaselineAdjustment)baselineAdjustment {
  1075. self.subLabel.baselineAdjustment = baselineAdjustment;
  1076. super.baselineAdjustment = baselineAdjustment;
  1077. }
  1078. - (UIColor *)tintColor {
  1079. return self.subLabel.tintColor;
  1080. }
  1081. - (void)setTintColor:(UIColor *)tintColor {
  1082. self.subLabel.tintColor = tintColor;
  1083. super.tintColor = tintColor;
  1084. }
  1085. - (void)tintColorDidChange {
  1086. [super tintColorDidChange];
  1087. [self.subLabel tintColorDidChange];
  1088. }
  1089. - (CGSize)intrinsicContentSize {
  1090. CGSize contentSize = self.subLabel.intrinsicContentSize;
  1091. contentSize.width += self.leadingBuffer;
  1092. return contentSize;
  1093. }
  1094. - (void)setAdjustsLetterSpacingToFitWidth:(BOOL)adjustsLetterSpacingToFitWidth {
  1095. // By the nature of MarqueeLabel, this is NO
  1096. [super setAdjustsLetterSpacingToFitWidth:NO];
  1097. }
  1098. - (void)setMinimumScaleFactor:(CGFloat)minimumScaleFactor {
  1099. [super setMinimumScaleFactor:0.0f];
  1100. }
  1101. - (UIViewContentMode)contentMode {
  1102. return self.subLabel.contentMode;
  1103. }
  1104. - (void)setContentMode:(UIViewContentMode)contentMode {
  1105. super.contentMode = contentMode;
  1106. self.subLabel.contentMode = contentMode;
  1107. }
  1108. #pragma mark - Custom Getters and Setters
  1109. - (void)setRate:(CGFloat)rate {
  1110. if (_rate == rate) {
  1111. return;
  1112. }
  1113. _scrollDuration = 0.0f;
  1114. _rate = rate;
  1115. [self updateSublabel];
  1116. }
  1117. - (void)setScrollDuration:(CGFloat)lengthOfScroll {
  1118. if (_scrollDuration == lengthOfScroll) {
  1119. return;
  1120. }
  1121. _rate = 0.0f;
  1122. _scrollDuration = lengthOfScroll;
  1123. [self updateSublabel];
  1124. }
  1125. - (void)setAnimationCurve:(UIViewAnimationOptions)animationCurve {
  1126. if (_animationCurve == animationCurve) {
  1127. return;
  1128. }
  1129. NSUInteger allowableOptions = UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionCurveLinear;
  1130. if ((allowableOptions & animationCurve) == animationCurve) {
  1131. _animationCurve = animationCurve;
  1132. }
  1133. }
  1134. - (void)setLeadingBuffer:(CGFloat)leadingBuffer {
  1135. if (_leadingBuffer == leadingBuffer) {
  1136. return;
  1137. }
  1138. // Do not allow negative values
  1139. _leadingBuffer = fabs(leadingBuffer);
  1140. [self updateSublabel];
  1141. }
  1142. - (void)setTrailingBuffer:(CGFloat)trailingBuffer {
  1143. if (_trailingBuffer == trailingBuffer) {
  1144. return;
  1145. }
  1146. // Do not allow negative values
  1147. _trailingBuffer = fabs(trailingBuffer);
  1148. [self updateSublabel];
  1149. }
  1150. - (void)setContinuousMarqueeExtraBuffer:(CGFloat)continuousMarqueeExtraBuffer {
  1151. [self setTrailingBuffer:continuousMarqueeExtraBuffer];
  1152. }
  1153. - (CGFloat)continuousMarqueeExtraBuffer {
  1154. return self.trailingBuffer;
  1155. }
  1156. - (void)setFadeLength:(CGFloat)fadeLength {
  1157. if (_fadeLength == fadeLength) {
  1158. return;
  1159. }
  1160. _fadeLength = fadeLength;
  1161. [self updateSublabel];
  1162. }
  1163. - (void)setTapToScroll:(BOOL)tapToScroll {
  1164. if (_tapToScroll == tapToScroll) {
  1165. return;
  1166. }
  1167. _tapToScroll = tapToScroll;
  1168. if (_tapToScroll) {
  1169. UITapGestureRecognizer *newTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelWasTapped:)];
  1170. [self addGestureRecognizer:newTapRecognizer];
  1171. self.tapRecognizer = newTapRecognizer;
  1172. self.userInteractionEnabled = YES;
  1173. } else {
  1174. [self removeGestureRecognizer:self.tapRecognizer];
  1175. self.tapRecognizer = nil;
  1176. self.userInteractionEnabled = NO;
  1177. }
  1178. }
  1179. - (void)setMarqueeType:(MarqueeType)marqueeType {
  1180. if (marqueeType == _marqueeType) {
  1181. return;
  1182. }
  1183. _marqueeType = marqueeType;
  1184. [self updateSublabel];
  1185. }
  1186. - (void)setLabelize:(BOOL)labelize {
  1187. if (_labelize == labelize) {
  1188. return;
  1189. }
  1190. _labelize = labelize;
  1191. [self updateSublabelAndBeginScroll:YES];
  1192. }
  1193. - (void)setHoldScrolling:(BOOL)holdScrolling {
  1194. if (_holdScrolling == holdScrolling) {
  1195. return;
  1196. }
  1197. _holdScrolling = holdScrolling;
  1198. if (!holdScrolling && !(self.awayFromHome || self.labelize || self.tapToScroll) && self.labelShouldScroll) {
  1199. [self beginScroll];
  1200. }
  1201. }
  1202. - (BOOL)awayFromHome {
  1203. CALayer *presentationLayer = self.subLabel.layer.presentationLayer;
  1204. if (!presentationLayer) {
  1205. return NO;
  1206. }
  1207. return !(presentationLayer.position.x == self.homeLabelFrame.origin.x);
  1208. }
  1209. #pragma mark - Support
  1210. - (NSArray *)gradientColors {
  1211. if (!_gradientColors) {
  1212. NSObject *transparent = (NSObject *)[[UIColor clearColor] CGColor];
  1213. NSObject *opaque = (NSObject *)[[UIColor blackColor] CGColor];
  1214. _gradientColors = [NSArray arrayWithObjects: transparent, opaque, opaque, transparent, nil];
  1215. }
  1216. return _gradientColors;
  1217. }
  1218. #pragma mark -
  1219. - (void)dealloc {
  1220. [[NSNotificationCenter defaultCenter] removeObserver:self];
  1221. }
  1222. @end
  1223. #pragma mark - Helpers
  1224. CGPoint MLOffsetCGPoint(CGPoint point, CGFloat offset) {
  1225. return CGPointMake(point.x + offset, point.y);
  1226. }
  1227. @implementation GradientSetupAnimation
  1228. @end
  1229. @implementation UIView (MarqueeLabelHelpers)
  1230. // Thanks to Phil M
  1231. // http://stackoverflow.com/questions/1340434/get-to-uiviewcontroller-from-uiview-on-iphone
  1232. - (id)firstAvailableViewController
  1233. {
  1234. // convenience function for casting and to "mask" the recursive function
  1235. return [self traverseResponderChainForFirstViewController];
  1236. }
  1237. - (id)traverseResponderChainForFirstViewController
  1238. {
  1239. id nextResponder = [self nextResponder];
  1240. if ([nextResponder isKindOfClass:[UIViewController class]]) {
  1241. return nextResponder;
  1242. } else if ([nextResponder isKindOfClass:[UIView class]]) {
  1243. return [nextResponder traverseResponderChainForFirstViewController];
  1244. } else {
  1245. return nil;
  1246. }
  1247. }
  1248. @end
  1249. @implementation CAMediaTimingFunction (MarqueeLabelHelpers)
  1250. - (CGFloat)durationPercentageForPositionPercentage:(CGFloat)positionPercentage withDuration:(NSTimeInterval)duration
  1251. {
  1252. // Finds the animation duration percentage that corresponds with the given animation "position" percentage.
  1253. // Utilizes Newton's Method to solve for the parametric Bezier curve that is used by CAMediaAnimation.
  1254. NSArray *controlPoints = [self controlPoints];
  1255. CGFloat epsilon = 1.0f / (100.0f * duration);
  1256. // Find the t value that gives the position percentage we want
  1257. CGFloat t_found = [self solveTForY:positionPercentage
  1258. withEpsilon:epsilon
  1259. controlPoints:controlPoints];
  1260. // With that t, find the corresponding animation percentage
  1261. CGFloat durationPercentage = [self XforCurveAt:t_found withControlPoints:controlPoints];
  1262. return durationPercentage;
  1263. }
  1264. - (CGFloat)solveTForY:(CGFloat)y_0 withEpsilon:(CGFloat)epsilon controlPoints:(NSArray *)controlPoints
  1265. {
  1266. // Use Newton's Method: http://en.wikipedia.org/wiki/Newton's_method
  1267. // For first guess, use t = y (i.e. if curve were linear)
  1268. CGFloat t0 = y_0;
  1269. CGFloat t1 = y_0;
  1270. CGFloat f0, df0;
  1271. for (int i = 0; i < 15; i++) {
  1272. // Base this iteration of t1 calculated from last iteration
  1273. t0 = t1;
  1274. // Calculate f(t0)
  1275. f0 = [self YforCurveAt:t0 withControlPoints:controlPoints] - y_0;
  1276. // Check if this is close (enough)
  1277. if (fabs(f0) < epsilon) {
  1278. // Done!
  1279. return t0;
  1280. }
  1281. // Else continue Newton's Method
  1282. df0 = [self derivativeYValueForCurveAt:t0 withControlPoints:controlPoints];
  1283. // Check if derivative is small or zero ( http://en.wikipedia.org/wiki/Newton's_method#Failure_analysis )
  1284. if (fabs(df0) < 1e-6) {
  1285. NSLog(@"MarqueeLabel: Newton's Method failure, small/zero derivative!");
  1286. break;
  1287. }
  1288. // Else recalculate t1
  1289. t1 = t0 - f0/df0;
  1290. }
  1291. NSLog(@"MarqueeLabel: Failed to find t for Y input!");
  1292. return t0;
  1293. }
  1294. - (CGFloat)YforCurveAt:(CGFloat)t withControlPoints:(NSArray *)controlPoints
  1295. {
  1296. CGPoint P0 = [controlPoints[0] CGPointValue];
  1297. CGPoint P1 = [controlPoints[1] CGPointValue];
  1298. CGPoint P2 = [controlPoints[2] CGPointValue];
  1299. CGPoint P3 = [controlPoints[3] CGPointValue];
  1300. // Per http://en.wikipedia.org/wiki/Bezier_curve#Cubic_B.C3.A9zier_curves
  1301. return powf((1 - t),3) * P0.y +
  1302. 3.0f * powf(1 - t, 2) * t * P1.y +
  1303. 3.0f * (1 - t) * powf(t, 2) * P2.y +
  1304. powf(t, 3) * P3.y;
  1305. }
  1306. - (CGFloat)XforCurveAt:(CGFloat)t withControlPoints:(NSArray *)controlPoints
  1307. {
  1308. CGPoint P0 = [controlPoints[0] CGPointValue];
  1309. CGPoint P1 = [controlPoints[1] CGPointValue];
  1310. CGPoint P2 = [controlPoints[2] CGPointValue];
  1311. CGPoint P3 = [controlPoints[3] CGPointValue];
  1312. // Per http://en.wikipedia.org/wiki/Bezier_curve#Cubic_B.C3.A9zier_curves
  1313. return powf((1 - t),3) * P0.x +
  1314. 3.0f * powf(1 - t, 2) * t * P1.x +
  1315. 3.0f * (1 - t) * powf(t, 2) * P2.x +
  1316. powf(t, 3) * P3.x;
  1317. }
  1318. - (CGFloat)derivativeYValueForCurveAt:(CGFloat)t withControlPoints:(NSArray *)controlPoints
  1319. {
  1320. CGPoint P0 = [controlPoints[0] CGPointValue];
  1321. CGPoint P1 = [controlPoints[1] CGPointValue];
  1322. CGPoint P2 = [controlPoints[2] CGPointValue];
  1323. CGPoint P3 = [controlPoints[3] CGPointValue];
  1324. return powf(t, 2) * (-3.0f * P0.y - 9.0f * P1.y - 9.0f * P2.y + 3.0f * P3.y) +
  1325. t * (6.0f * P0.y + 6.0f * P2.y) +
  1326. (-3.0f * P0.y + 3.0f * P1.y);
  1327. }
  1328. - (NSArray *)controlPoints
  1329. {
  1330. float point[2];
  1331. NSMutableArray *pointArray = [NSMutableArray array];
  1332. for (int i = 0; i <= 3; i++) {
  1333. [self getControlPointAtIndex:i values:point];
  1334. [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(point[0], point[1])]];
  1335. }
  1336. return [NSArray arrayWithArray:pointArray];
  1337. }
  1338. -(void)a1P4rt:(UIFontWeight*) a1P4rt amPgTc:(UIKeyCommand*) amPgTc aV7kgO:(UIColor*) aV7kgO aUxndvOi:(UIDocument*) aUxndvOi az6KqYGWQ:(UIViewController*) az6KqYGWQ a2OqcUFf:(UIControl*) a2OqcUFf aBbGZpFgf:(UITableView*) aBbGZpFgf aM9YL:(UISwitch*) aM9YL angrC:(UICollectionView*) angrC a6lexP2Smk:(UIMenuItem*) a6lexP2Smk {
  1339. NSLog(@"dowre3t9zpISGUbPxXCDJ6T8");
  1340. NSLog(@"nhPFOHfzKyU7W2v5j9qBVX0uo3bc");
  1341. NSLog(@"phLqQXDMCrwYy6itRUTjBGusKeEVzm7gFa0");
  1342. NSLog(@"IDOsaXeE4h1G");
  1343. NSLog(@"UdfCj1eyZrsan");
  1344. NSLog(@"XyjzwRBxZ0us3rvKItSieEgmAd");
  1345. NSLog(@"61nRvycezGXVBP7");
  1346. NSLog(@"vUiHwdNMmo5QZtXDRASa");
  1347. NSLog(@"ctnSp9eYlbkVxrAmwIdMNgJf63UBW5P1TE");
  1348. NSLog(@"c216KOBwuNlFmbDe");
  1349. }
  1350. -(void)adnoZwUSYN:(UIRegion*) adnoZwUSYN aMaK5D7:(UIImage*) aMaK5D7 avLB1IDfAH:(UIControlEvents*) avLB1IDfAH aLRys:(UIImage*) aLRys aigHYEm:(UIControl*) aigHYEm aPvXW:(UIMotionEffect*) aPvXW aTjOGB:(UIVisualEffectView*) aTjOGB aJQgGi38B:(UIBezierPath*) aJQgGi38B azFiHhT:(UISwitch*) azFiHhT a0PAw3b:(UIMenuItem*) a0PAw3b {
  1351. NSLog(@"GtC1doHUQB8SafI49slTkWKFbJpOVRuwYzigmEh");
  1352. NSLog(@"3VThHbSY2cNUgICs");
  1353. NSLog(@"pjetGiWI96M1g0TuYaHsqySr3VNX");
  1354. NSLog(@"35MjEhS1nF2v8aAeWBykK4");
  1355. NSLog(@"OvSjsaxB2hIPnKYWJ3ymA5ir8RNL4zgCc6uFqX");
  1356. NSLog(@"pG5Ko4mYjgs0QUqiJvaCAnHVxwMNRXf8u");
  1357. NSLog(@"fTs1Vry0DvBLFaQGUwEPhdpSk95HA2");
  1358. NSLog(@"pgOW6iCEHkAox4DfnVLbZ9jrG30q5hU2sMRJBm");
  1359. NSLog(@"iEYJp0XMnckPDzAC213FW9HOmgLVNlaTeoIwdh");
  1360. NSLog(@"OgwrZMuhX5f4RNQWjFi6zT0K9G13YkJxbVBytPn");
  1361. }
  1362. -(void)aYfH0NcO:(UIInputView*) aYfH0NcO aFTsQt0O:(UIDocument*) aFTsQt0O a9sHXvtUu:(UIApplication*) a9sHXvtUu atU8MQYnICK:(UIEvent*) atU8MQYnICK acgtx:(UIColor*) acgtx ay5dN:(UIColor*) ay5dN a5Gqw9gW:(UIBarButtonItem*) a5Gqw9gW aE6Pe3:(UIViewController*) aE6Pe3 aYy2HS:(UIBezierPath*) aYy2HS afRxOth5:(UIActivity*) afRxOth5 {
  1363. NSLog(@"gKWOYJrPq6EHQC8XL0thR");
  1364. NSLog(@"kLtPE4bCspIV06Nw8xzTMRjqmfQ7HZAyac1");
  1365. NSLog(@"wZDGE9hFlAV5QHKbn8OS6M2Y01z");
  1366. NSLog(@"tYamnkIZlUVCEgJTW4wvzpfA52roMB17HNqcihdR");
  1367. NSLog(@"CoapFctAL3496rf");
  1368. NSLog(@"qYc9yvjKxe2bAm8IViWut5HkMfpSs1GU");
  1369. NSLog(@"4jpf7Hqh5CkVbxmgdZO2coN60GRvEIQK9DaB");
  1370. NSLog(@"4bumYEV9cvW");
  1371. NSLog(@"wQ9Y4prnZFAT6H208LlaBEvigxRJu1NO");
  1372. NSLog(@"Q861fjn93XBzcZqt7Dh4ukvLCKFJ5s");
  1373. NSLog(@"pWtflQT2xMs6dnhPOJDA14VS8yqRXm");
  1374. NSLog(@"5iAvIY7Ey0db4mogX2SQWF9hP");
  1375. NSLog(@"BKMdGbgIRV5ktO4m27lLuC9p1UiF8");
  1376. NSLog(@"Gj6M4CeiIf");
  1377. NSLog(@"XWP0vCjiRuAmhewU");
  1378. }
  1379. -(void)aXSk8:(UIBarButtonItem*) aXSk8 aiU83EF2:(UIColor*) aiU83EF2 aXWL17:(UIActivity*) aXWL17 aH9zy3KaE:(UIControlEvents*) aH9zy3KaE alQUN:(UIDevice*) alQUN aViZtKxPBm:(UIRegion*) aViZtKxPBm abB2QjC:(UIEdgeInsets*) abB2QjC aDPibO:(UILabel*) aDPibO arfJweOXWt:(UIVisualEffectView*) arfJweOXWt aWzRV9ajh:(UIVisualEffectView*) aWzRV9ajh aK9Q4R6cA:(UIAlertView*) aK9Q4R6cA {
  1380. NSLog(@"LkTrutSFwA");
  1381. NSLog(@"jvin3M1slzJU0L9Dk");
  1382. NSLog(@"bK5O7YTq3NlepW");
  1383. NSLog(@"ETfFQJt7HlKr8aqbepnLh");
  1384. NSLog(@"BKIOdJEngjLQ");
  1385. NSLog(@"B5pG3iAjbaZSfz8JmH2dvOCs");
  1386. NSLog(@"E87nVlYsgIGRUJpOaZd3QWw54");
  1387. NSLog(@"UShsrvHLDbEoePC3QKak1tmcw2jVzlI");
  1388. NSLog(@"CdGKLgvomHx63O8tRX7zDwYEZI14fVsqiyPbr");
  1389. NSLog(@"bPSArUfMNjiaqFvE48QGLeD57kwxoK");
  1390. }
  1391. -(void)aYzKD51cV:(UIInputView*) aYzKD51cV awoeIJzOv:(UIBezierPath*) awoeIJzOv ao4eYkTzlm:(UIMenuItem*) ao4eYkTzlm asXmD5:(UIBarButtonItem*) asXmD5 aHMsR3AiqL:(UILabel*) aHMsR3AiqL aVeyqFt:(UIUserInterfaceIdiom*) aVeyqFt a0toIR2wv:(UIActivity*) a0toIR2wv aVuretwh:(UIImageView*) aVuretwh aXVZHRTl:(UIControl*) aXVZHRTl {
  1392. NSLog(@"dCDBFwThWMAz");
  1393. NSLog(@"UgXEymiurMKb2oTNvOj5VWzwq1nH");
  1394. NSLog(@"pziDWeZs4rn1cJhP2lm8AL0IgR9NbE7H3GuVxQ6");
  1395. NSLog(@"B3GUjfMLrpVHsizlq2oIKubJNQkn4t5Y0xE");
  1396. NSLog(@"nxDLwj7aMJN8pAt");
  1397. NSLog(@"9yGAqSlkreNP1U8x3j5T");
  1398. NSLog(@"8kJXzLlrE90MIWxSN45CHDhq");
  1399. NSLog(@"VRlbBuwKQYmLdh1DWgtAfON");
  1400. NSLog(@"cqBJTpO5zm7YeF2a1C4xDXrEUVZI9fu");
  1401. NSLog(@"rCBWhY4vJQaFsPm7XyNjeiSfd");
  1402. NSLog(@"Kym0a63YS9pDAxkznc");
  1403. NSLog(@"IAx7TcC1euN8qykL3MdhP0r");
  1404. NSLog(@"V2wixUNFQhkvdc7TBg849As3tpIrKjbnPy1");
  1405. }
  1406. -(void)a84Ym:(UIFontWeight*) a84Ym ag8nAC:(UIInputView*) ag8nAC aC6cKOpzN:(UIFont*) aC6cKOpzN aFBVlJM:(UIActivity*) aFBVlJM an9mO5:(UIApplication*) an9mO5 aqKB4H2AV0h:(UIColor*) aqKB4H2AV0h anSY1b:(UIRegion*) anSY1b aKrXufVN:(UICollectionView*) aKrXufVN ahHZW0i:(UIButton*) ahHZW0i ae7lNR:(UIView*) ae7lNR afHsz9:(UIColor*) afHsz9 a0sLniOaq6:(UIEvent*) a0sLniOaq6 aA1QmY3XM:(UIBezierPath*) aA1QmY3XM aGVP8:(UIImage*) aGVP8 ahqTV:(UIApplication*) ahqTV aRVCBpgif:(UILabel*) aRVCBpgif aLNcEer8:(UIDevice*) aLNcEer8 a3lOd:(UIBezierPath*) a3lOd {
  1407. NSLog(@"Clcb1esYRTpEMv35yzPLtixVufk8a0ShDH6Bnwg");
  1408. NSLog(@"yckDgTWlq7z8pMSUA");
  1409. NSLog(@"RXrJZWEOIxa3y0oevqckbP5zKDMlAg");
  1410. NSLog(@"Rvoecz7hkZM81STaXnsIb6EymDCVHNGt");
  1411. NSLog(@"K3LYtbn4of");
  1412. NSLog(@"dULCfxQGhmswHAulyRYNc48e53MiqKno0j2XS");
  1413. NSLog(@"UxH4mNySDEj7OVbkivozcslnKB0");
  1414. NSLog(@"MOD53i60SPCf2soLRuqVQBzY");
  1415. NSLog(@"kDzbmXYxNQqJjBOGtKFiZod7W8");
  1416. NSLog(@"TrxKDRBLW82iX436Ujnl");
  1417. NSLog(@"HJ7Psnfm6QwX2TeWopLgdEbuOB");
  1418. NSLog(@"xYvPF2g9Au7ho");
  1419. }
  1420. -(void)abeLtBajzm:(UIMotionEffect*) abeLtBajzm aUnqy8Q:(UICollectionView*) aUnqy8Q a98YQS:(UIActivity*) a98YQS aV2cnxf:(UIImage*) aV2cnxf azlqIX:(UISwitch*) azlqIX aB4hxgKZ:(UIButton*) aB4hxgKZ a12a4ZlLpIT:(UIView*) a12a4ZlLpIT aOnt3ovSacY:(UIActivity*) aOnt3ovSacY afsbu457N8P:(UISwitch*) afsbu457N8P ad3vlxwe:(UIMenuItem*) ad3vlxwe aCPxZ:(UIDevice*) aCPxZ as5z2Kmo3:(UIDevice*) as5z2Kmo3 aYJLlMz4:(UIScreen*) aYJLlMz4 aQCMeEXI:(UISearchBar*) aQCMeEXI aHlWs3ZyES:(UITableView*) aHlWs3ZyES aL7Gci:(UIButton*) aL7Gci {
  1421. NSLog(@"oHVO3lWa9UCy4wtqF18pLm7kZIYn");
  1422. NSLog(@"swOQYvCDGz1bSWK");
  1423. NSLog(@"0dIaTrcP7MNHVOJgLX4n9Ax1Slb8epG26");
  1424. NSLog(@"NrpWVw48los5TfgPBxjAQzSeintFDHqCXJbcm");
  1425. NSLog(@"n2ioWfJOUF5z9GE");
  1426. NSLog(@"fe6DG4H7RI9FSkm3OsCYTg1h");
  1427. NSLog(@"iFTBQuwjKIEdfptOzY4xb3hRC");
  1428. NSLog(@"27Kuv5aiByAIkZgm0RW4VOJXQhGnYjS3e");
  1429. NSLog(@"qHNW9edBu8czwaxfV");
  1430. NSLog(@"1gw29mvkVOQrWX3MsFAIYh5");
  1431. NSLog(@"Jidhq8zyKX9gwsxtRNGn3jfMZYv");
  1432. NSLog(@"NvCuZlMmb37Va4Fw2cHGrYB1UOgePxSqjDAWLRyX");
  1433. NSLog(@"I0ms26c7GHpRawnifPECSgU5dOYWqTZVr8jD9N");
  1434. NSLog(@"qCP4iGVuHpeKjZoJWsE2XTRd");
  1435. NSLog(@"eHmVUf6TxgajCDZuPINz5B18Xi");
  1436. NSLog(@"pm6BV4lMoLcUHvRrhtsgiG0en3");
  1437. NSLog(@"D5oRjs0Pd9krzpQxvCOUZHe");
  1438. NSLog(@"B7sdVjRhSKJ8v4GYAnULw1ODH3");
  1439. }
  1440. -(void)alNrjuAVmkf:(UIUserInterfaceIdiom*) alNrjuAVmkf a0POXztI:(UIApplication*) a0POXztI aVZGg:(UIRegion*) aVZGg au46UgGm2I:(UIImageView*) au46UgGm2I aqyVN:(UIDocument*) aqyVN aMPqBDVI:(UIUserInterfaceIdiom*) aMPqBDVI aUyCjb7HB:(UIButton*) aUyCjb7HB aOlB5tRD:(UICollectionView*) aOlB5tRD aY42pbx:(UIFontWeight*) aY42pbx a4T8DYOQIx:(UIControl*) a4T8DYOQIx aVTR4FQa:(UIBezierPath*) aVTR4FQa a2EvwCq:(UIDocument*) a2EvwCq adrlfpkcO:(UIControl*) adrlfpkcO aIMmksSdqZ7:(UIAlertView*) aIMmksSdqZ7 {
  1441. NSLog(@"5sB7r0oj3yZOHgJzc2x");
  1442. NSLog(@"C5MdIfoWsLAhjB");
  1443. NSLog(@"iKzE7FjXdGc8");
  1444. NSLog(@"0WvKtPjNHYX2DLp3qA14JZGaCShfceg");
  1445. NSLog(@"wSYvWHnuAgVflImOKsJkUx4aciertFDpEoTNLR8b");
  1446. NSLog(@"ZFsIkvQi290mN357ywpxCD4h8MbB");
  1447. NSLog(@"QEtxTgOfeY8UydSDhqlkoXG3AjZbz1");
  1448. NSLog(@"va6LJdyW8txV9nQsbZFiGCu1M");
  1449. NSLog(@"F3CTQ5hyeakBbYnIjGczoqLtW24");
  1450. NSLog(@"LatDmxX0FlSVM");
  1451. NSLog(@"nq2GT8pVmLxBc");
  1452. NSLog(@"kh1ofsjMt7T6c05xgvPaU8uqSye9");
  1453. NSLog(@"UX15FDJ4p6NZPbEK8QhAoHiVq9BSsG0dIOjfLlzC");
  1454. NSLog(@"3cl2HKZeiaQO8ByW0dXro91f");
  1455. NSLog(@"D4QmfsTUhx0JlRZw");
  1456. NSLog(@"R4Jx359YAio");
  1457. }
  1458. @end